有没有办法从IDataReader将DEFAULT关键字传递给SqlBulkCopy?
基本上相当于
INSERT INTO MyTable(NonNullableWithDefault)
VALUES (DEFAULT)
在我的应用程序中,目标表具有不可为空的列,并且对它们有默认约束 要上传的部分数据包含这些列的值,有些则没有 对于没有值的行(DBNull),它应该使用默认约束。
如this answer中所述,SqlBulkCopy要求您根本不传递ColumnMapping或发送值。
替代方案我正在考虑
我不能成为第一个遇到这个问题的人 人们在这种情况下使用了什么?
更新
经过多次摆弄后,我现在用一个查询获取整个数据库结构,然后将该数据集传递给我的datareaders。
SELECT
columns.TABLE_SCHEMA schemaName
, columns.TABLE_NAME tableName
, columns.TABLE_SCHEMA + '.' + columns.TABLE_NAME fullTableName
, columns.COLUMN_NAME columnName
, columns.DATA_TYPE dataType
, ISNULL(columns.CHARACTER_MAXIMUM_LENGTH, -1) charlength
, columns.COLUMN_DEFAULT defaultValue
, columns.ORDINAL_POSITION ordinalPosition
FROM
information_schema.columns columns
默认值字符串的解析并不漂亮,很可能不适合高级情况。然而,在我们的案例中,它涵盖了所有基础。
private object ParseDefault(DataRow row)
{
if(row.IsNull("defaultValue")) return null;
var value = row.Field<string>("defaultValue");
if (value == "(getdate())")
{
return DateTime.UtcNow;
}
var type = GetTypeForName(row.Field<string>("dataType"));
return ParseCell(value.Trim('(', ')'), type);
}
private static object ParseCell(string value, Type info)
{
if (value.Equals("NULL", StringComparison.OrdinalIgnoreCase))
{
return DBNull.Value;
}
int intValue;
if (info == typeof(bool) && int.TryParse(value, out intValue))
{
return intValue == 1;
}
var foo = TypeDescriptor.GetConverter(info);
return foo.ConvertFromInvariantString(value);
}
优点:
缺点
答案 0 :(得分:1)
有没有办法从IDataReader将DEFAULT关键字传递给SqlBulkCopy?
不幸的是,没有。 :-(如果列为NOT NULL
并且您的批量插入映射到该列,则每行必须具有该列的值。
背景:在TDS级别,通过发送使用仅外部工具语法后跟INSERT
statement包含列元数据然后行的SQL TDS structures来完成批量插入数据。这些都没有提供说明方式&#34;如果NULL
值在非NULL
能力列中,请将NULL
视为DEFAULT
。&# 34;
嗯......当感觉应该有内置的,简单的解决方案而且所有选项都很痛苦时,它会令人沮丧。 : - /如果不了解您的情况,很难知道推荐哪个选项。人们在这种情况下使用了什么?
另外一个选项:占位符值方法。在插入之前,替换应该默认的&#34; NULL
&#34;具有占位符值。然后,插入后,运行更新以使用数据库生成的默认值(例如UPDATE ... SET Col1 = DEFAULT WHERE Col1 = *placeholder*
)替换占位符。您的应用程序必须知道哪些非可空列具有默认值,但不必知道如何计算默认值。我不关心它,因为它使用所谓的魔术数字 - 但它是一种选择。