2012-02-10 37 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