2011-05-06 101 views
1

我已经实现了一个应用程序,它从csv文件中获取数据并插入到Sql DB中,我使用Linq到sql。我也有要求skipping那些有一些验证的记录, 达到此目的我使用了一个循环,并在循环内调用submitchnages()。批量从csv插入到数据库使用Linq到sql

问题:此应用程序的记录数量较少(< 100),但实际上不适合获取更多3 - 4个记录的csv文件。我只是简单地运行我的应用程序对这些大文件,结果应用程序需要很长时间(5 - 6小时)。

请提出任何更好的方法。

+0

发布相关的代码? – 2011-05-06 22:34:31

回答

3

Linq-to-SQL非常适合获取数据库的数据,或者一次性验证和少量插入/更新。但是对于你正在做的事情(ETL),听起来像你需要查看SqlBulkCopy对象。继续使用你的L2S对象来进行验证,但是不要提交更改,只需将对象映射到一个好的旧式ADO.NET DataTable中,并且每隔1000条记录就可以批量插入它们。

+0

提及'SqlBulkCopy'。 – Steven 2011-05-07 15:02:53

1

如果性能是一个大问题,LINQ to SQL可能不是这项工作的工具。然而,折腾的LINQ to SQL出你的解决方案的大门之前,你可能会考虑以下几点:

  • 尝试一定数量的记录后,创建一个新的DataContextDataContext缓存所有发送到数据库并从数据库中检索的实体,这将导致大量内存占用并最终...内存不足。
  • 使用SQL事件探查器查看LINQ to SQL发送到数据库的查询。可能的话,LINQ to SQL也会为您创建的每个实体查询数据库。
  • 尝试调整插入数据库。这可能很困难,但您可以尝试将这些记录写入中间表(具有较少的依赖关系),并使用存储过程将数据移动到最终目标。

批量插入是O/RM不擅长的事情,所以您可能需要采取不同的方法。

1

如果您必须使用Linq2Sql进行插入操作,则可能需要进行间歇性提交。像这样 -

public void LoadLargeDataUsingLinqToSql(string pathToCSV){ 
     DataTable dt = LoadMyCSVToDataTable(pathToCSV); 
     int myPerformanceCounter = 0; 
     foreach(DataRow dr in dt.Rows()){ 
      MyLinqClass m = ConvertDRToMyLinqClass(dr); 
      if(m.IsValidAndReadyToBeSaved()){ 
       MyDataContext.MyLinqClassRef.InsertOnSubmit(m); 
       myPerformanceCounter++; 
      } 

      if(myPerformaceCounter>25000){ 
       //Commit to clear cache. 
       MyDataContext.SubmitChanges(); 
       myPerformanceCounter=0; 
      } 
     } 
     //Commit leftovers 
     MyDataContext.SubmitChanges(); 
    } 
+0

'SubmitChanges'不清除'DataContext'的内部缓存。它将坚持所有的对象,甚至提交一次。你应该在调用'SubmitChanges()'后创建一个新的'DataContext'。 – Steven 2011-05-07 15:02:00

+0

按缓存我并不是指DataContext缓存。我的意思是等待提交给数据库的对象的逻辑缓存。创建新的数据环境并不总是可行的,除非你有一个非常严格的“工作单元”实现。 SQLBulk副本是典型数据加载程序的首选方法,但如果您想坚持纯粹的基于对象的模型,那么这种方法可以正常工作。在一分钟内插入几十万个物体。 – YetAnotherUser 2011-05-07 17:40:23

+0

请参阅http://blogs.msdn.com/b/dinesh.kulkarni/archive/2008/07/01/linq-to-sql-tips-9-understanding-datacontext-s-internal-caching.aspx。 L2S缓存不是一个非常昂贵的缓存。 – YetAnotherUser 2011-05-07 17:43:47