2010-10-12 65 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); 
    } 
} 
相關問題