2010-08-17 57 views
10

我有一個父子表關係。在倉庫,我這樣做:EF永久生成此查詢

return (from p in _ctx.Parents 
.Include("Children") 
select p).AsQueryable<Parent>(); 

然後在過濾器中,我想孩子ID列表來過濾父:

IQueryable<Parent> qry; // from above 
List<int> ids; // huge list (8500) 
var filtered = 
from p in qry.Where(p => p.Children.Any(c => ids.Contains(c.ChildId))) select s; 

我的ID列表是巨大的。這會生成一個簡單的SQL語句,其中包含一個巨大的ID列表(「(1,2,3 ...)」),但它本身不需要可觀的時間運行。然而,EF只需要大約一分鐘時間來生成聲明。我通過設置斷點和呼叫證明了這一點:

((ObjectQuery<Parent>)filtered).ToTraceString(); 

這需要所有的時間。在我最後的linq聲明中是否存在問題?我不知道有任何其他方式可以完成(ids)中的Child.ChildId。即使我的linq聲明不好,世界上該怎麼走這麼久?

+0

發佈你的模式和生成的sql,你可能會得到更多的幫助。 – 2010-08-17 16:32:03

+0

模式似乎並不重要,父母/子女關係也不重要。同樣的問題只是從一個大型列表中選擇一個表/實體。 – dudeNumber4 2010-08-19 15:15:58

+0

對於遇到問題的任何人;從我能說的一切來看,EF4沒有解決方案。您必須訴諸存儲過程。更多信息:http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/d629c798-db45-4a04-9813-a3b565d87c83 – dudeNumber4 2010-08-23 15:20:15

回答

2

用Lambda語法重新編寫查詢,它會將時間縮短3秒(或者至少對我的EF項目來說)。

return _ctx.Parents.Include("Children").AsQueryable<Parent>(); 

IQueryable<Parent> qry; // from above 
List<int> ids; // huge list (8500) 
var filtered = qry.Where(p => p.Children.Any(c => ids.Contains(c.ChildId))); 
+0

'Select(s => s)'什麼都不做。在哪裏結束它。 – StriplingWarrior 2010-08-24 00:16:52

+0

正確...謝謝! – 2010-08-24 05:00:53

+0

這對我的情況沒有任何影響。 – dudeNumber4 2010-08-24 13:54:23

4

不幸的是,在建築的LINQ查詢實體是一個相當沉重的打擊,但我發現它通常可以節省時間,由於之前建立從他們的組成部件查詢的能力實際上擊中了數據庫。

他們實現Contains方法的方式很可能使用一種算法,該算法假定Contains通常用於相對較小的一組數據。根據我的測試,在列表中每個ID花費的時間量開始在8000左右飆升。

因此,它可能有助於將您的查詢分解爲碎片。將它們分組爲1000或更少的組,並連接一堆Where表達式。

var idGroups = ids.GroupBy(i => i/1000); 
var q = Parents.Include("Children").AsQueryable(); 
var newQ = idGroups.Aggregate(q, 
    (s, g) => s.Concat(
        q.Where(w => w.Children.Any(wi => g.Contains(wi.ChildId))))); 

這顯著提高速度,但它可能沒有足夠顯著你的目的,在這種情況下,你將不得不訴諸一個存儲過程。不幸的是,這個特定的用例不適合預期實體框架行爲的「框」。如果您的id列表可以從同一個實體上下文開始查詢,那麼實體框架可以正常工作。

+0

Upvoted,但沒有標記爲答案。使用存儲的特效是答案,但我不打算使用破壞的查詢解決方案。我只是使用破損的EF解決方案... – dudeNumber4 2010-08-24 13:56:47

+0

我會鼓勵你開始賞金或標記答案。即使您爲自己的問題編寫自己的基於存儲過程的答案,常見問題清楚地表明這是可以接受的。當然,我還要指出,我不僅按照要求回答了問題,而且還提供瞭解決方案,聽起來就像您打算使用的那樣。 – StriplingWarrior 2010-08-24 16:12:30

+0

這可能是您要得到的最佳答案。由於有人爲框架解決問題,這就是答案。 – 2010-08-24 19:21:12