2012-08-07 71 views
4

我有製表符分隔的文本文件。文件大約100MB。我想將這個文件中的數據存儲到SQL服務器表中。當存儲在sql server中時,該文件包含100萬條記錄。達到此目的的最佳方法是什麼?使用c分隔文本文件在SQL Server表中批量插入數據#

我可以在c#中創建momory數據表,然後上傳到sql服務器,但在這種情況下,它會加載整個100 MB文件到內存。如果文件大小變大怎麼辦?

+0

爲什麼不只是'BULK INSERT'命令? – 2012-08-07 06:39:42

+0

@pst如果我沒有弄錯,那就要求該文件與SQL Server位於同一臺服務器上,這可能是我知道的海報 – Cocowalla 2012-08-07 06:42:34

回答

4

沒問題; CsvReader將處理大多數分隔文本格式,並實現IDataReader,因此可用於提供SqlBulkCopy。例如:

using (var file = new StreamReader(path)) 
using (var csv = new CsvReader(file, true)) // true = first row is headers 
using (var bcp = new SqlBulkCopy(connectionString)) 
{ 
    bcp.DestinationTableName = "Foo"; 
    bcp.WriteToServer(csv); 
} 

注意CsvReader有很多的選擇更多更微妙的文件處理(指定分隔符規則等)。 SqlBulkCopy是高性能批量加載API - 非常高效。這是一個流式讀寫器API;它不會立即加載所有的數據到內存中。

+0

的問題。這是由某人開發的,並在MIT開放源代碼許可下。我正在尋找的是使用微軟提供的SDK來實現相同目標的最佳方式。無需額外的許可證。 – 2012-08-07 06:52:47

+1

@SamirLakhani MIT許可證非常開放,並允許您免費使用代碼的許可證,前提是您在發佈的作品中包含其許可證:http://en.wikipedia.org/wiki/MIT_License – Cocowalla 2012-08-07 06:56:56

2

您應仔細閱讀文件中的行由行,所以你不必整行加載到內存:

using (var file = System.IO.File.OpenText(filename)) 
{ 
    while (!file.EndOfStream) 
    { 
     string line = file.ReadLine(); 

     // TODO: Do your INSERT here 
    } 
} 

*更新*

這將使100萬個單獨的插入命令到SQL服務器有沒有什麼辦法使其成批量

你可以使用參數化查詢,它仍然會發布1M插入,但仍然會很快。

或者,您可以使用SqlBulkCopy,但如果您不想使用第三方庫,那將會相當困難。如果你是更適合的MS許可,您可以使用LINQ Entity Data Reader(下發布的MS-PL許可證),它提供了AsDataReader擴展方法:

void MyInsertMethod() 
{ 
    using (var bulk = new SqlBulkCopy("MyConnectionString")) 
    { 
     bulk.DestinationTableName = "MyTableName"; 
     bulk.WriteToServer(GetRows().AsDataReader()); 
    } 
} 

class MyType 
{ 
    public string A { get; set; } 
    public string B { get; set; } 
} 

IEnumerable<MyType> GetRows() 
{ 
    using (var file = System.IO.File.OpenText("MyTextFile")) 
    { 
     while (!file.EndOfStream) 
     { 
      var splitLine = file.ReadLine().Split(','); 

      yield return new MyType() { A = splitLine[0], B = splitLine[1] }; 
     } 
    } 
} 

如果你不想使用MS許可的代碼你也可以自己實現IDataReader,但那將是一個PITA。請注意,上述的CSV處理(Split(','))完全沒有問題,並且表中的列名必須與MyType上的屬性名相同。 TBH,我建議你和Marc一起回答這個問題

+1

@pst I有人認爲海報知道如何做到這一點從 – Cocowalla 2012-08-07 06:43:19

+0

這個問題的措辭這將使100萬個單獨的插入命令到SQL服務器。有沒有什麼辦法可以批量生產 – 2012-08-07 06:56:52

+0

@Cocowalla爲什麼SqlBulkCopy很難沒有第三方庫?我正在做下面的方式,它看起來不錯: SqlBulkCopy bulkCopy = new SqlBulkCopy(...) bulkCopy.BulkCopyTimeout = 0; bulkCopy.DestinationTableName =「

」; bulkCopy.WriteToServer(dt); 其中dt是我通過解析文件填充的DataTable。使用StreamReader。 – 2012-08-07 13:52:43

相關問題