回答
只需從您的對象列表中選擇create a DataTable,然後調用SqlBulkCopy.WriteToServer
,傳遞數據表。
您可能會發現下面的有用:
- Adding columns to a DataTable。爲您希望編寫的每個屬性/字段添加一列。
- Adding rows to a DataTable。爲列表中的每個對象添加一行。
爲了獲得SqlBulkCopy的最佳性能,您應該設置合適的BatchSize。 10,000似乎運作良好 - 但對您的數據進行了描述。
使用SqlBulkCopyOptions.TableLock時,您可能會觀察到更好的結果。
SqlBulkCopy性能的一個有趣的和翔實的分析可以找到here。
隨着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
本身中指定它們,您可能希望使用SqlBulkCopy
的ColumnMappings
方面)。
根據您試圖通過首先調用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萬行文本文件。
遲到了,但如果添加此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);
}
}
- 1. 從列表中返回一個列表<SomeType><AnotherType>
- 2. 從列表返回一個匹配<KeyValuePair <string,string >>
- 3. C#搜索列表<t>另一個列表<T>
- 4. 從列表<>
- 5. 從列表<>
- 6. 比較一個列表<T>與另一個列表<t>
- 7. 序列化列表<一個LinkedListNode <object>>使用Json.net
- 8. 兩個BackgroundWorkers,一個列表<T>
- 9. 將5個列表<object>合併成一個列表<object>
- 10. 從另一個過濾一個列表<string>通過LINQ
- 11. 列表<Object>和列表<?>
- 12. 一類從列表<T>
- 13. 更新一個列表<T>從另一個列表中<T>當數據變化
- 14. 從列表中獲取唯一值<Dictionary <string,string >>
- 15. 如何轉換番石榴,列表<String>和列表<Integer>在另一個列表<Person>?
- 16. 從列表<Customer>獲取列表<int>使用linq
- 17. 創建列表<CustomObject>從列表<string>
- 18. 無法從列表<T>轉換爲列表<T>
- 19. 提取列表<>從列表<>
- 20. 從列表<myType>繼承或擴展列表<myType>
- 21. 無法從列表<Bar>轉換到列表<Foo>
- 22. 從XML構建列表<列表<XElement>>
- 23. 從列表<class>
- 24. C#JSON從列表<>
- 25. WCF從列表<T>
- 26. 從列表<>在C#
- 27. 轉換列表<T>到列表<string>一般
- 28. 在列表中搜索一個值<Dictionary <string,object >>
- 29. 比較一個List <列表<decimal>>
- 30. 如何創建一個列表<Item<T>>
遲到了,但是如果你添加這個'EntityDataReader'類,那麼就有一個'AsDataReader()'擴展方法,它的確如此:https:// github。com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – RJB 2016-04-23 21:52:38
(請參閱下面的全新實施答案) – RJB 2016-04-23 22:31:13