2010-10-12 62 views
21

如何使用SqlBulkCopy从简单对象的列表<>大插入?SqlBulkCopy从一个列表<>

我是否实现了我的自定义IDataReader?

+0

迟到了,但是如果你添加这个'EntityDataReader'类,那么就有一个'AsDataReader()'扩展方法,它的确如此:https:// github。com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – RJB 2016-04-23 21:52:38

+0

(请参阅下面的全新实施答案) – RJB 2016-04-23 22:31:13

回答

19

只需从您的对象列表中选择create a DataTable,然后调用SqlBulkCopy.WriteToServer,传递数据表。

您可能会发现下面的有用:

为了获得SqlBulkCopy的最佳性能,您应该设置合适的BatchSize。 10,000似乎运作良好 - 但对您的数据进行了描述。

使用SqlBulkCopyOptions.TableLock时,您可能会观察到更好的结果。

SqlBulkCopy性能的一个有趣的和翔实的分析可以找到here

40

随着FastMember,你可以这样做而没有通过需要DataTable(在我的测试中,更比加倍性能)去:

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) 
{ 
    bcp.DestinationTableName = "SomeTable"; 
    bcp.WriteToServer(reader); 
} 

注意ObjectReader也可以与非工作并且没有必要预先指定成员名称(尽管如果您没有在ObjectReader本身中指定它们,您可能希望使用SqlBulkCopyColumnMappings方面)。

+0

优秀的图书馆!我刚刚尝试过,效果很好。 – alex 2013-06-08 07:50:00

+0

我知道这是几个月前,但我有一个类似的问题。首先加载'DataTable'花费的时间太长,所以我想使用这种方法。然而,params变量中列出的字符串是从基础数据结构迭代的对象开始依次使用的变量的实际名称? – JNYRanger 2013-10-18 17:25:52

+0

划痕 - 计算出来,答案是肯定的,那些是对象内属性的名称。 – JNYRanger 2013-10-18 18:16:13

1

根据您试图通过首先调用SqlBulkCopy来完成的工作,使用Table-Valued Parameter(TVP)可能更有意义。使用TVP将使发送任何自定义类型的集合变得微不足道。数据可以流入,因此您可以避免DataTable(很像在@Marc Gravell的答案中),您也可以避免SqlBulkCopy。当你调用一个存储过程传递TVP数据时,TVP允许完全灵活地处理数据,一旦它到达SQL Server,它就表现为表变量,你可以做任何事情,而不仅仅是INSERT(这是情况与SqlBulkCopy)。您也可以通过SqlDataReader获取数据,例如新创建的IDENTITY值。我在这个答案中增加了一个例子和一些附加注释:How can I insert 10 million records in the shortest time possible?。几年前,我写了一篇关于SQL Server Central的文章(需要免费注册),Streaming Data Into SQL Server 2008 From an Application,这也在该链接的答案中提到,提供了一个传递自定义类型的通用列表的工作示例,从300万行文本文件。

5

迟到了,但如果添加此Microsoft EntityDataReader类,有一个AsDataReader()扩展方法正是这么做的:https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

(例如[List].AsDataReader()实现:)

var connStr = ""; 
using (var connection = new SqlConnection(connStr)) 
{ 
    var startTime = DateTime.Now; 
    connection.Open(); 
    var transaction = connection.BeginTransaction(); 
    try 
    { 
     //var connStr = connection.ConnectionString; 
     using (var sbCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction)) 
     { 
      sbCopy.BulkCopyTimeout = 0; 
      sbCopy.BatchSize = 10000; 
      sbCopy.DestinationTableName = "Foobars"; 
      var reader = Foobars.AsDataReader(); 
      sbCopy.WriteToServer(reader); 
     } 
     transaction.Commit(); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
     transaction.Rollback(); 
    } 
    finally 
    { 
     transaction.Dispose(); 
     connection.Close(); 
     var endTime = DateTime.Now; 
     Console.WriteLine("Upload time elapsed: {0} seconds", (endTime - startTime).TotalSeconds); 
    } 
} 
相关问题