我知道很多次都会问这个问题,但我的问题略有不同:
我的要求如下:
我有一个约有的文本文件。 50000行,文件差不多10 MB。
每一行都有固定大小的值,如下所示:
0001 abcdefgh 1234567 xyz
0002 pqrst 02233 abc
003 asddfd 545 slfkk
它不是分隔符或逗号分隔等。
我有一个sql表,结构如下:
code varchar(5)
name varchar(18)
phone varchar(16)
address varchar(20)
我需要完成的是当客户点击按钮时,它应该清空sql表并从文本文件中读取新记录(因为这是一个ASP.net应用程序,我使用WCF服务来读取文件并将字符串传递给服务器,其工作正常)。
拆分和保存到数据库的代码如下:
Service1Client client = new Service1Client();
string data = client.ReadFile(@"C:\testfolder\test.txt");
context.Database.ExecuteSqlCommand(@"DELETE FROM table1");
table1 c;
using (StringReader reader = new StringReader(data))
{
string line = "";
while ((line = reader.ReadLine()) != null)
{
c = new table1();
c.Code = line.Substring(0, 5).Trim();
c.name= line.Substring(5, 18).Trim();
c.phone= line.Substring(23, 16).Trim();
c.address = line.Substring(39, 20).Trim();
context.table1.Add(c);
}
}
context.SaveChanges();
}
client.Close();
但这种方法至少需要30分钟才能复制所有记录。有没有更好的方法加快这个?
感谢
答案 0 :(得分:1)
读取文件不是花时间,而是插入数据库。 我会以下面的方式修改它,而不是一次性执行更新,以较小的批次执行:
您可以通过更改if
语句来测试性能,以查看您在批处理中插入的行数。
using (StringReader reader = new StringReader(data))
{
string line = "";
int counter = 0;
while ((line = reader.ReadLine()) != null)
{
c = new table1();
c.Code = line.Substring(0, 5).Trim();
c.name= line.Substring(5, 18).Trim();
c.phone= line.Substring(23, 16).Trim();
c.address = line.Substring(39, 20).Trim();
context.table1.Add(c);
if (counter == 10){
context.SaveChanges();
counter =0;
}
else{
counter++;
}
}
context.SaveChanges();
}
或者,您可以设计一个producer/consumer
模型,其中文件的读取与数据库插入无关,因此实质上您将运行2个线程,1个线程读取,另一个插入数据库。将多于一个的线程插入到DB中将无济于事,但是独立于DB插入的读取可能会提高整体性能。
答案 1 :(得分:1)
作为数据库主管,我打算说" BCP"但是......使用SqlBulkCopy。见文章:
http://msdn.microsoft.com/en-us/library/7ek5da1a%28v=vs.110%29.aspx
" Microsoft SQL Server包含一个名为bcp的流行命令行实用程序,用于将大型文件快速批量复制到SQL Server数据库中的表或视图中。 SqlBulkCopy类允许您编写提供类似功能的托管代码解决方案。还有其他方法可以将数据加载到SQL Server表中(例如INSERT语句),但SqlBulkCopy比它们具有显着的性能优势。"
答案 2 :(得分:0)
你一次只读一行,这是非常低效的。您应该使用BufferedStream:
缓冲区是内存中用于缓存数据的字节块,从而 减少对操作系统的调用次数。缓冲区改善 读写性能。缓冲区可用于读取或 写作,但从不同时。读写方法 BufferedStream自动维护缓冲区。
答案 3 :(得分:0)
进行中介SaveChanges并用新的上下文替换你的上下文:
context.Configuration.AutoDetectChangesEnabled = false;
int lines = 0;
int batchSize=50;
using (StringReader reader = new StringReader(data))
{
string line = "";
while ((line = reader.ReadLine()) != null)
{
c = new table1();
c.Code = line.Substring(0, 5).Trim();
c.name= line.Substring(5, 18).Trim();
c.phone= line.Substring(23, 16).Trim();
c.address = line.Substring(39, 20).Trim();
context.table1.Add(c);
if (lines++ % batchSize == 0)
{
context.SaveChanges();
context = new DataContext();
context.Configuration.AutoDetectChangesEnabled = false;
}
}
}
context.SaveChanges();
您可以调整batchSize