2017-05-29 46 views
0

有沒有辦法將DEFAULT關鍵字從IDataReader傳遞給SqlBulkCopy?
基本的將DEFAULT關鍵字傳遞給不可空列與SqlBulkCopy

INSERT INTO MyTable(NonNullableWithDefault) 
VALUES (DEFAULT) 

在我的應用程序相當於目標表必須與他們默認約束不爲空的列。
一些要上傳的數據具有這些列的值,有些則沒有。
對於沒有值的行(DBNull),它應該使用默認約束。

this answer所述,SqlBulkCopy要麼根本不傳入ColumnMapping,要麼發送一個值。

替代我考慮

  • 分裂的數據在不同的columnmappings(復)爲默認
  • 檢查DB通過,並在DataReader的填充它們(慢)
  • 創建單獨的轉儲表沒有約束(複雜,也許很慢)

我不能成爲第一個有這個問題的人。
人們在這種情況下使用什麼?

UPDATE

多少擺弄周圍我現在有一個查詢取我的整個數據庫的結構,然後通過該數據集到我的DataReader之後。

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); 
} 

優點:

  • 不可爲空的默認值解決辦法
  • 清除驗證消息(例如最大長度)
  • 手柄柱名的情況下的匹配

缺點

  • 解析默認字符串值
  • 無法解析SQL方面的默認值(如存儲過程)

回答

1

有沒有辦法從一個IDataReader的傳遞DEFAULT關鍵字來使用SqlBulkCopy?

不幸的是,沒有。 :-(如果一列是NOT NULL並且您的批量插入映射到它,則每行必須具有該列的值。

背景:在TDS水平,大容量插入由包含列元數據然後行數據發送使用外部工具僅語法隨後寫入一個SQL INSERT statementTDS structures通過完成。這些都沒有提供說「如果NULL值在非NULL列中,將NULL視爲DEFAULT」。

人們在這種情況下使用什麼?

嗡嗡...當感覺應該有內置的簡單解決方案,而是所有的選項都很痛苦時,這很令人沮喪。 : - 不知道更多關於你的情況,很難知道推薦哪個選項。

一個附加選項:佔位符值方法。在插入之前,用佔位符值替換應該默認的「NULL」。然後,在插入後,運行更新以使用數據庫生成的默認值替換佔位符(例如UPDATE ... SET Col1 = DEFAULT WHERE Col1 = *placeholder*)。你的應用程序必須知道哪些不可​​爲空的列有默認值,但不需要知道如何計算默認值。我不關心它,因爲它使用了所謂的魔術數字 - 但它是一個選項。

+1

感謝您的解釋。我仍然希望找到更好的方法,否則我可能不得不訴諸大量的插入:( –

+0

@BorisCallens,我和你在一起 - 我真的很想聽到更好的方法來做到這一點! !如果你找到一個並且有時間,請在這裏發佈。 –

+1

我的下一個想法是首先獲取所有的默認約束(請參閱https://stackoverflow.com/questions/141682/how-do-i-find-a -default-constraint-using-information-schema),並在我的IDataReader中用我自己的默認值替換NULL,但我暫時插入了多個值。 –