我有制表符分隔的文本文件。文件大约100MB。我想将此文件中的数据存储到SQL Server表。存储在sql server中时,该文件包含100万条记录。实现这一目标的最佳方法是什么?
我可以在c#中的momory数据表中创建,然后将其上传到sql server,但在这种情况下,它会将整个100 MB的文件加载到内存中。如果文件大小变大怎么办?
答案 0 :(得分:5)
没问题; 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; 不一次将所有数据加载到内存中。
答案 1 :(得分:2)
您应该逐行阅读文件,因此您不必将整行加载到内存中:
using (var file = System.IO.File.OpenText(filename))
{
while (!file.EndOfStream)
{
string line = file.ReadLine();
// TODO: Do your INSERT here
}
}
*更新*
“这将向sql server发出100万个单独的插入命令。有没有办法批量制作”
你可以使用参数化查询,它仍会发出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的回答