2012-02-10 35 views
13

批量插入我有一個查詢,看起來像這樣:使用LINQ到SQL

using (MyDC TheDC = new MyDC()) 
{ 
    foreach (MyObject TheObject in TheListOfMyObjects) 
    { 
     DBTable TheTable = new DBTable(); 

     TheTable.Prop1 = TheObject.Prop1; 
     ..... 
     TheDC.DBTables.InsertOnSubmit(TheTable); 

    } 
    TheDC.SubmitChanges(); 
} 

該查詢基本上插入一個列表到使用LINQ到SQL數據庫。現在我在線閱讀了L2S不支持批量操作。 我的查詢是通過一次插入每個元素還是所有元素都在一次寫入中工作的?

感謝您的澄清。

回答

7

術語Bulk Insert通常指的是基於SQL Server特定超快bcp的SqlBulkCopy實現。它建立在IRowsetFastLoad之上。

Linq-2-SQL不使用此機制實現插入,在任何條件下。

如果需要批量加載數據到SQL Server,並需要它要快,我會建議使用手工編碼的SqlBulkCopy。

的Linq-2-SQL將嘗試進行一些優化技術來加快多個插件,但它仍然會功虧一簣許多微奧姆斯的(即使沒有微奧姆斯我知道的實施SqlBulkCopy的)

3

它會生成每個記錄單插入語句,而是將它們全部發送到服務器單批和運行在一個單一的交易。

這是的SubmitChanges()外循環做什麼。

如果內移動,然後通過循環每次迭代都會去關閉服務器的INSERT和在它自己的事務中運行。

我不相信有什麼辦法把火關SQL BULK INSERT。

+0

http://stackoverflow.com/a/1329094/17174沒有L2S測試插入PERF的對抗了一陣短小精悍,但我沒有測試EF VS短小精悍...漂亮的結果令人失望for ef https://gist.github.com/1623514 – 2012-02-10 01:37:22

26

我修改了代碼從下面的鏈接更高效,並在我的應用程序中使用它。這非常方便,因爲您可以將它放在當前自動生成的類的頂級分類中。而不是InsertOnSubmit添加實體到列表中,而不是SubmitChanges調用YourDataContext.BulkInsertAll(list)

http://www.codeproject.com/Tips/297582/Using-bulk-insert-with-your-linq-to-sql-datacontex

partial void OnCreated() 
{ 
    CommandTimeout = 5 * 60; 
} 

public void BulkInsertAll<T>(IEnumerable<T> entities) 
{       
    using(var conn = new SqlConnection(Connection.ConnectionString)) 
    { 
     conn.Open(); 

     Type t = typeof(T); 

     var tableAttribute = (TableAttribute)t.GetCustomAttributes(
      typeof(TableAttribute), false).Single(); 
     var bulkCopy = new SqlBulkCopy(conn) 
     { 
      DestinationTableName = tableAttribute.Name 
     }; 

     var properties = t.GetProperties().Where(EventTypeFilter).ToArray(); 
     var table = new DataTable(); 

     foreach (var property in properties) 
     { 
      Type propertyType = property.PropertyType; 
      if (propertyType.IsGenericType && 
       propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
      { 
       propertyType = Nullable.GetUnderlyingType(propertyType); 
      } 

      table.Columns.Add(new DataColumn(property.Name, propertyType)); 
     } 

     foreach (var entity in entities) 
     { 
      table.Rows.Add(
       properties.Select(
       property => property.GetValue(entity, null) ?? DBNull.Value 
       ).ToArray()); 
     } 

     bulkCopy.WriteToServer(table); 
    }            
} 

private bool EventTypeFilter(System.Reflection.PropertyInfo p) 
{ 
    var attribute = Attribute.GetCustomAttribute(p, 
     typeof(AssociationAttribute)) as AssociationAttribute; 

    if (attribute == null) return true; 
    if (attribute.IsForeignKey == false) return true; 

    return false; 
} 
+0

使用Linqpad我必須't.GetProperties()。Where(EventTypeFilter)'''t.GetFields()'。 插入200k行多一分鐘! (y) – 2017-12-07 12:38:26

+0

不能贊成這足夠。我的212條記錄的測試插入是50秒,這將它縮減到1.3秒。當我實際插入10k記錄時應該有所幫助! – Ian 2017-12-20 04:28:00

+0

檢查了這一點:https://stackoverflow.com/a/21382542/1246870 - 爲我工作得很好 – avs099 2018-01-25 01:24:59