回答
只需從您的對象列表中選擇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. 從列表<>
- 4. 序列化列表<一個LinkedListNode <object>>使用Json.net
- 5. 兩個BackgroundWorkers,一個列表<T>
- 6. 將5個列表<object>合併成一個列表<object>
- 7. 從另一個過濾一個列表<string>通過LINQ
- 8. 列表<Object>和列表<?>
- 9. 更新一個列表<T>從另一個列表中<T>當數據變化
- 10. 從XML構建列表<列表<XElement>>
- 11. 從列表<myType>繼承或擴展列表<myType>
- 12. 提取列表<>從列表<>
- 13. 無法從列表<Bar>轉換到列表<Foo>
- 14. 從列表<class>
- 15. C#JSON從列表<>
- 16. 從列表<>在C#
- 17. 轉換列表<T>到列表<string>一般
- 18. Collections.emptyList()返回一個列表<Object>?
- 19. 從LINQ查詢創建一個字典<INT,列表<int>>
- 20. 更新列表<select>從另一個<select multiple>使用jquery
- 21. 類的設計 - 返回一個列表<Object>從<Object>
- 22. 檢查列表<string>是否包含在另一個列表<string>
- 23. C#重新排序列表<string>基於另一個列表<string>
- 24. 轉換列表<T>到包含另一個列表<T>
- 25. 從列表中創建一個單一的項目列表<string><object>
- 26. 從匹配兩個分開的列表中獲取一個列表<T><T> s
- 27. 列表<Product>。加入(列表<Order>,...)與列表<Order>。加入(列表<Product>,...)?
- 28. 列表<>與多個列表C#
- 29. 無法從列表<map <string,object >>轉換爲列表<map <string,string >>
- 30. 加入多個列表<string[]>到一個新列表
遲到了,但是如果你添加這個'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