来自List 的SqlBulkCopy

如何从简单对象的List 中使用SqlBulkCopy进行大插入?

我是否实现了自定义IDataReader?

只需从对象列表中创建一个DataTable ,然后调用SqlBulkCopy.WriteToServer ,传递数据表。

您可能会发现以下内容有用:

  • 将列添加到DataTable 。 为要写入的每个属性/字段添加一列。
  • 将行添加到DataTable 。 为列表中的每个对象添加一行。

为了使用SqlBulkCopy获得最佳性能,您应该设置适当的BatchSize 。 10,000似乎运作良好 – 但您的数据配置文件。

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

可以在此处找到有关SqlBulkCopy性能的有趣且信息丰富的分析。

使用FastMember ,您可以在不需要通过DataTable (在我的测试中,性能提高一倍以上)的情况下执行此操作:

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

请注意, ObjectReader也可以使用非generics源,并且不必事先指定成员名称(尽管如果不在ObjectReader本身中指定它们,您可能希望使用SqlBulkCopyColumnMappings方面)。

晚了,但是如果你从微软添加这个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); } } 

根据您尝试通过首先调用SqlBulkCopy来完成的任务,使用表值参数(TVP)可能更有意义。 使用TVP会使发送任何自定义类型的集合变得微不足道。 数据可以流式传输,因此您可以避免使用DataTable (很像@Marc Gravell的答案),您也可以避免使用SqlBulkCopy 。 当您调用存储过程将TVP数据传入其中时,TVP允许完全灵活地处理数据到达SQL Server,并且它显示为可以执行任何操作的表变量,而不仅仅是INSERT (这是使用SqlBulkCopy情况)。 您还可以通过SqlDataReader获取数据,例如新创建的IDENTITY值等数据。 我在这个答案中添加了一个示例和一些附加说明: 如何在最短的时间内插入1000万条记录? 。 几年前我写了一篇关于SQL Server Central的文章(需要免费注册), 从一个应用程序将数据流式传输到SQL Server 2008 ,这也是在链接的答案中提到的,提供了一个传递自定义通用列表的工作示例类型,从300万行文本文件中流入。