2013-02-06 52 views
15

我想找到一種使用Linq過濾導航屬性到相關實體子集的方法。我知道解決這個問題的所有答案,建議做一個匿名的選擇,例如:EntityFramework 5過濾一個包含的導航屬性

query.Where(x => x.Users.Any(y => y.ID == actingUser.ID)) 
    .Select(x => new 
    { 
     Event = x, 
     Discussions = x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>()) 
    }) 
    .OrderBy(x => x.Discussions.Count()) 
    .ThenBy(x => x.Event.Name); 

然而,這是理想顯著較少,由於我們的查詢生成的一般性質,也產生顯著可怕的SQL查詢,如果你扔了探查。

我希望能夠完成這樣的:

query.Include(x => x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())) 
     .OrderBy(x => x.Discussions.Count()) 
     .ThenBy(x => x.Name); 

我知道這是不是在EF5(或與此有關的任何版本)的支持,但必須有完成約束的方式結果集通過Linq而不需要深入研究匿名類型選擇語句。

我試圖做一些的調整:

query.GroupJoin(discquqery, 
    x => x.ID, 
    x => x.Event.ID, 
    (evt, disc) => evt.Discussions = disc.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())).ToList(); 

但是你不能有一個lambda表達式內部分配和這裏選擇一個匿名類型會導致同樣的困境,它並使用選擇。

我想我無法理解爲什麼EF不提供方式(即我能找到),以產生:

SELECT 
    --Properties 
FROM Event e 
LEFT OUTER JOIN Discussions d 
    ON e.ID = d.EventID AND --Additional constraints 
WHERE 
    --Where conditions 
ORDER BY 
    --Order Conditions 

它是如此簡單約束在SQL存在的加入是一個辦法做到它也通過Linq。

PS:我已經搜索過堆棧,MSDN,專家交換等請認識到這不是重複的。甚至任何涉及這個問題的東西都有一個「不能做」答案或根本沒有答案。沒有什麼是不可能的......包括這個

+1

那麼,這裏是一個「它可以做到」的答案:http://stackoverflow.com/a/13904825/861716 –

+5

有很多方法可以在EF中擴展查詢生成引擎。所以這不是不可能的,如果這是唯一的路線,那麼答案就是EF查詢引擎的擴展,以允許INNER/OUTER JOIN包含額外的過濾器。沒有什麼是不可能的......如果我必須重新編譯EF,那麼我會......它沒有現有的答案意味着答案是自己構建它(我現在甚至當我問這個問題,計劃在做什麼) – VulgarBinary

+4

這就是精神!! –

回答

8

任何事情甚至觸及這個問題或有一個警察「它不能 被做」答案或根本沒有答案。沒有什麼是不可能的...... 包括這一點。

肯定。有可能的。您可以下載EF源代碼並自行添加此功能。這將對開源項目和社區做出巨大貢獻。我相信EF團隊會很樂意幫助您的努力。

隨着當前版本「它不能做」is the answer。您可以使用投影到匿名或特殊的未映射類型,正如您在問題開始時所描述的那樣。其他選項是單獨的顯式查詢,用於爲單個父代加載相關實體或單獨查詢以加載所有父代的相關實體。

單親負載關係:

context.Entry(event) 
     .Collection(e => e.Discussions) 
     .Query() 
     .Where(d => ...) 
     .Load(); 

所有家長負載關係(需要延遲加載被關閉):

// load all parents 
var events = query.Where(e => ...).ToList(); 

// load child filtered by same condition for parents and new condition for children 
childQuery.Where(d => e.Event ... && d.Something ...).Load(); 

第二種方法則需要孩子有導航屬性回父級(用於構建最初用於加載父級的相同查詢條件)。如果你已經正確配置了所有東西並且連接了實體,那麼EF應該會自動修正父實體中的關係(集合)(但它不會將動態代理中的集合標記爲已加載,這就是爲什麼你不能在延遲加載時使用它的原因)。

+0

然後顯然我擴展了EF5內核。你知道是否有辦法擴展而不是修改和重新編譯整個DLL? – VulgarBinary

+1

您將不得不重新編譯該DLL。您可以訪問[EF codeplex網站](http://entityframework.codeplex.com/discussions)並直接與EF團隊討論這一貢獻 - 他們可能已經爲此功能設計了一些高級設計並與您分享。 –

+3

投票過濾包括[這裏](https://entityframework.codeplex.com/workitem/47)! – Chris

相關問題