我最近注意到一些奇怪的東西,Entitiy上的導航屬性並沒有實現IQueryable,而據我所知檢索一個單一的實體,然後在導航屬性上鍊接運算符可能會導致許多(每項1個)調用數據庫,從生成的代碼中,我發現在單個大型查詢中有一個帶有子查詢結果的大型查詢(如果可能)。爲什麼linq中的子導航中的實體的導航屬性沒有實現IQueryable?
但是我想知道它是如何工作的,因爲在子查詢中可用的重載與在子查詢之外的導航屬性上調用的重載相同。 問題1:我的猜測是,即使它在IEnuerable上,而任何調用本身是傳遞到where的表達式的一部分,它就會被構建到在where和parsed處生成的單個表達式樹中,而不是作爲單獨的表達式因爲它本身不是一個表達),這是正確的嗎?
問題2:如果#1是正確的,如果你在只能在運行時在委託中進行的表達式外創建代碼,這是如何工作的(例如,如果我通過PredicateExprEntityTwo.Compile( ),在q5中,編譯時不會編譯和失敗,因爲編譯器不知道編譯時表達式中func的用法?
問題3:假設我有#1和# 2正確的,這個設計的優點與在那裏做表達式有什麼關係?我遇到的缺點是,對於業務驗證,我想有一組謂詞,其中包含業務邏輯,用於過濾相同類型的實體程序中的許多地方,但我可能想要在子查詢中使用它們假設#2是正確的,重複使用同一個可能是不可行的?
對不起,如果問題聽起來有點混亂,但我只注意到上週我有IEnumerables重載在子查詢中調用,但仍然是一個單一的EF查詢作爲輸出,我很好奇這可能是如何工作。
public class Class1
{
void Test()
{
Func<Entity1, bool> PredicateFuncEntityOne = i => i.Id == 2;
Expression<Func<Entity1, bool>> PredicateExprEntityOne = i => i.Id == 2;
Func<Entity2, bool> PredicateFuncEntityTwo = i => i.Id == 2;
Expression<Func<Entity2, bool>> PredicateExprEntityTwo = i => i.Id == 2;
using (var Context = new TestModelContainer())
{
// Works as this expects an expression
var q1 = Context.Entity1Set.Where(PredicateExprEntityOne);
// Works but would call the IEnumerable version
var q2 = Context.Entity1Set.Where(PredicateFuncEntityOne);
// This compiles, any on item.Entity2 expects a func on IEnumerable, not IQueryable overload
var q3 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateFuncEntityTwo));
// This fails for the reason mentioned above
var q4 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateExprEntityTwo));
// Does this work and if so how is it possible?
var q5 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateExprEntityTwo.Compile()));
}
}
}
你好,雖然這是安慰它並沒有真正回答我的問題,我真的在尋找規範級別的答案,因爲我即將圍繞它制定一些強大的程序設計決策,同時我可以測試我寧願有一個清晰的解釋,以及whys(特別是因爲我建議是反直覺相比,將這些標記爲IQueryable,我真的想知道如果我失去了一些東西)。 – 2011-05-09 23:24:24