2012-08-07 75 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

相关问题