2016-05-27 72 views
3

有沒有人知道什麼是最有效的方式是檢查存在多個項目(最多1000)在一個大的數據庫表(1,000,000行+),看看他們是否需要添加,使用EF/Linq/SQL Server數據庫(託管在Azure上)?最有效的方法來檢查是否存在多個項目

目前,我的性能非常低下(儘管當我最初在本地Sql數據庫上開發時,性能要好得多),使用以下兩種方法。

我是否需要考慮將EF留給這個任務,並直接針對db運行一些SQL?

//loop to check all imported items against db 
private void ImportNewSerialsWorkerUsingLoopCheck(List<foo> importedFoos) 
{ 
    List<foos> foosToAddToDb = new List<foo>(); 
    foreach (var foo in importedFoos) 
    { 
     fooCheck = context.Foos.FirstOrDefault(f => f.Serial == foo.Serial); 
     if (fooCheck == null) 
     { 
      foosToAddToDb.Add(foo); 
     } 
    } 
    context.foos.AddRange(foosToAddToDb); 
} 


//use Any() to check all imported items against db 
private void ImportNewSerialsWorkerUsingAnyCheck(List<foo> importedFoos) 
{ 
    var foosToAddToDb = importedFoos.Where(i => !context.foos.Any(f => f.Serial == i.Serial)).ToList();  
    context.foos.AddRange(foosToAddToDb); 
} 

更新

我剛剛運行對本地SQL數據庫SQL事件探查器跟蹤,而在var foosToAddToDb = importedFoos.Where(i => !context.foos.Any(f => f.Serial == i.Serial)).ToList();命令使用.Any() LINQ命令,發現EF運行時,它爲每個單獨的SQL查詢項目importedFoos,所以在使用該方法時看起來沒有任何優勢。

回答

4

你的第二個片段是執行一個EF查詢作爲Linq到對象查詢的一部分,因此它爲什麼執行每個項目的查詢。您只需執行一個EF查詢即可執行一次往返數據庫的操作。

var serials = importedFoos. Select(foo => too.Serial); 
var existing = context.Foos.Where(foo => serials.Contains(foo.Serial)); 
var toAdd = importedFoos.Except(existing); 
+0

Ah謝謝Servy,會放棄這一切,我已經犯了不必要的.ToList()調用的過去。 – Ted

+0

@Ted如果'importedFoos'實際上是一個EF查詢,你不必要的物化,那麼這很容易。只要不實現它並編寫'context.Foos.Except(importedFoos);'你就完成了,並且也是最有效的實現。 – Servy

相關問題