列不允许 DBNull.Value - 禁止 KeepNulls - 正确的列映射

2024-02-23

我正在使用 c# 和 .NET 4.5.2,推送到 SQL Server 2017 14.0.1000.169

在我的数据库中,我有一个带有 DateAdded 字段的表,其类型为DateTimeOffset.

我正在尝试使用以下代码进行批量复制:

private Maybe BulkCopy(SqlSchemaTable table, System.Data.DataTable dt, bool identityInsertOn)
{
    try
    {
        var options = SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.UseInternalTransaction; //  | SqlBulkCopyOptions.CheckConstraints; // Tried CheckConstraints, but it didn't change anything.
        if (identityInsertOn) options |= SqlBulkCopyOptions.KeepIdentity;
        using (var conn = new SqlConnection(_connString))
        using (var bulkCopy = new SqlBulkCopy(conn, options, null))
        {
            bulkCopy.DestinationTableName = table.TableName;
            dt.Columns.Cast<System.Data.DataColumn>().ToList()
                .ForEach(x => bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(x.ColumnName, x.ColumnName)));

            try
            {
                conn.Open();
                bulkCopy.WriteToServer(dt);
            }
            catch (Exception ex)
            {
                return Maybe.Failure(ex);
            }
        }
    }
    catch (Exception ex)
    {
        return Maybe.Failure(ex);
    }

    return Maybe.Success();
}

我所知道的两个可能的原因does not allow DBNull错误是:

  1. 列的顺序错误,可以通过将它们按照与数据库序号相同的顺序放置或执行列映射来解决。
  2. KeepNulls 已启用,并且DBNull.Value (or null?)在数据表中设置。

但我正确映射并且从未设置 KeepNulls。

但我收到错误:

列 DateAdded 不允许 DBNull.Value

EDIT我也尝试过不设置任何东西,包括null, DBNull.Value, and DefaultValue...只是字面上根本没有设置该列。

另外,如果我从数据表中删除 DateAdded 列,它就可以工作。但我不想要这样。在这 100,000 条记录中,可能有 20 条有数据。因此,在我的 500 个批次中,有时 DateAdded 字段中没有数据,有时一两个有数据。

所以我想将该列保留在我的数据表中,但让它使用默认值。

最后一点:我交替将 DataColumn 的值设置为DBNull.Value versus dt.Columns[x.ColumnName].DefaultValue。两种方法都会给出相同的错误。

Edit 2

这是我用来填充数据表中的数据的代码:

foreach (var column in table)
{
    System.Data.DataRow newRow = dt.NewRow();
    foreach (var field in column)
    {
        if (!IsNull(field.Value) && !IsEmptyDateOrNumber(field.ColumnType, field.Value))
        {
            // For DateAdded, this is not hit on the first batch, though there are columns Before and After DateAdded on the same row which do have value.
            // But it WILL be hit once or twice a few batches later.  So I don't want to completely remove the definition from the DataTable.
            newRow[field.ColumnName] = field.Value;
        }
        else
        {
            // newRow[field.ColumnName] = dt.Columns[field.ColumnName].DefaultValue;
            // newRow[field.ColumnName] = DBNull.Value;
            // dt.Columns[field.ColumnName].AllowDBNull = true;
        }
    }
    dt.Rows.Add(newRow);
}

IsNull()回报TRUE如果值为null或字符串"null",这是我的业务需求所必需的。

IsEmptyDateOrNumber()将返回TRUE如果字段是数字或日期类型,并且值为 null 或空""。因为虽然空对于许多类似字符串的字段有效,但它永远不是有效的数值。

恰好满足为字段赋值的条件0%这个特定专栏的时间。因此什么都没有设定。


简而言之,你无法做你想做的事。有关 BulkCopy 如何使用默认值的最佳参考是这个答案 https://stackoverflow.com/questions/27027013/sqlbulkcopy-into-table-that-default-column-values-fails-when-source-datatable-ro/27044891#27044891鲁茨基.

问题是,BulkCopy 包括一个查询目标数据库并确定表结构的步骤。如果确定目标列是NOT NULL如果您传递 null 或 DBNull,它会在尝试传递数据之前引发异常。

如果您使用 SQL Profiler,您将看到 BCP 调用,但看不到数据(无论如何,数据永远不会显示)。您将看到的只是定义列列表和标志的调用。

当 BulkCopy 最终决定传递数据时。如果该列存在,且该字段为NULL能够,并且值为DBNull.Value,并且该列有一个默认值;批量复制本质上是通过DEFAULT标记该列。但做出了一些决定,使得这些条件,除非该领域是NOT NULL能够,不应该使用默认值,而是应该抛出异常。

据我所知,这是微软的一个错误或疏忽。

正如其他一些答案所述,常见的解决方法是通过计算代码中的值来手动处理这些值。当然,如果您计算默认值,那么 DBA 会更改某个字段的实际 SQL 默认值,您的系统将不匹配。下一步是向您的系统添加一个子系统,该子系统从您正在访问的 SQL Server 查询和/或跟踪/缓存当前指定的默认值,并分配这些值。这比需要做的工作多得多。

TLDR:你不能做你想做的事。但其他人指定了一些次优的解决方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

列不允许 DBNull.Value - 禁止 KeepNulls - 正确的列映射 的相关文章

  • 使用 CMake 时如何导出 Emscripten 中的 C 函数

    In 本教程 https emscripten org docs porting connecting cpp and javascript Interacting with code html interacting with code
  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • 将类对象放置在向量中?

    我注意到我可以将一个类放置在一个向量中 这是我的程序 我收到以下错误 out blackjack exe blackjack obj blackjack obj error LNK2019 unresolved external symbo
  • Rx.NET 中是否有一个Subject 实现,其功能类似于BehaviourSubject,但仅在值发生更改时才发出?

    有没有Subject https learn microsoft com en us previous versions dotnet reactive extensions hh229699 v vs 103 Rx NET 中的实现在功能
  • 有些有助于理解“产量”

    在我不断追求少吸的过程中 我试图理解 产量 的说法 但我不断遇到同样的错误 someMethod 的主体不能是迭代器块 因为 System Collections Generic List 不是迭代器接口类型 这是我被卡住的代码 forea
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • RestSharp获取序列化输出

    我正在寻找一种方法来访问 AddBody 调用的序列化结果 我正在使用内置的 RestSharp 序列化器 例子 class Foo public string FooField void SendRecord var f new Foo
  • 如何在 C# Designer.cs 代码中使用常量字符串?

    如何在 designer cs 文件中引用常量字符串 一个直接的答案是在我的 cs 文件中创建一个私有字符串变量 然后编辑 Designer cs 文件以使用此变量 而不是对字符串进行硬编码 但设计者不喜欢这样抛出错误 我明白为什么这行不通
  • 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

    我注意到CallContext LogicalSetData LogicalGetData不按照我期望的方式工作 内部设置的值async方法得到恢复即使没有异步或任何类型的线程切换 无论如何 这是一个简单的例子 using System u
  • 如何使用 ASP.NET Core 获取其他用户的声明

    我仍在学习 ASP NET Core 的身份 我正在进行基于声明的令牌授权 大多数示例都是关于 当前 登录用户的 就我而言 我的 RPC 服务正在接收身份数据库中某个用户的用户名和密码 我需要 验证是否存在具有此类凭据的用户 获取该用户的所
  • 如何将AVFrame转换为glTexImage2D使用的纹理?

    如您所知 AVFrame 有 2 个属性 pFrame gt data pFrame gt linesize 当我从视频 sdcard test mp4 android平台 读取帧后 并将其转换为RGB AVFrame副 img conve
  • 模板外部链接?谁能解释一下吗?

    模板名称具有链接 3 5 非成员函数模板可以有内部链接 任何其他模板名称应具有外部链接 从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同 我知道使用关键字的外部链接 extern C EX extern C templat
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • 将函数参数类型提取为参数包

    这是一个后续问题 解包 元组以调用匹配的函数指针 https stackoverflow com questions 7858817 unpacking a tuple to call a matching function pointer
  • 使动态创建的链接标签在 Winforms 中可点击

    我正在制作一个程序 允许用户单击由动态链接标签创建的公司名称 在我想知道如何做到这一点之前 我从未在 C 中使用过链接标签 可为特定用户生成的业务数量各不相同 因此每个用户的链接标签数量并不相同 然后我想捕获业务 ID 以进行 Json 调
  • 将 Lambda 表达式树与 IEnumerable 结合使用

    我一直在尝试了解有关使用 Lamba 表达式树的更多信息 因此我创建了一个简单的示例 这是代码 如果作为 C 程序粘贴到 LINQPad 中 它可以工作 void Main IEnumerable
  • 代码中的.net Access Forms身份验证“超时”值

    我正在向我的应用程序添加注销过期警报 并希望从我的代码访问我的 web config 表单身份验证 超时 值 我有什么办法可以做到这一点吗 我认为您可以从 FormsAuthentication 静态类方法中读取它 这比直接读取 web c
  • 了解 Lambda 表达式和委托 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我已经尝试解决这个问题很长一段时间了 阅读在线博客和文章 但到目前为止还没有成功 什么是代表 什么是 Lambda 表达式 两者的优点
  • 如何在 sql azure 上运行 aspnet_regsql? [复制]

    这个问题在这里已经有答案了 可能的重复 将 ASP NET 成员资格数据库迁移到 SQL Azure https stackoverflow com questions 10140774 migrating asp net membersh

随机推荐