我正在使用 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
错误是:
- 列的顺序错误,可以通过将它们按照与数据库序号相同的顺序放置或执行列映射来解决。
- 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%这个特定专栏的时间。因此什么都没有设定。