2011-05-06 166 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