2010-03-30 30 views
2

我想在linq查詢中分離出經常使用的表達式。我正在使用實體框架4和LINQKit,但我仍然不知道如何以正確的方式進行操作。讓我舉個例子:如何在EFI(和LINQKit)中使用Linq中的外部表達式?

Article article = dataContainer.Articles.FirstOrDefault(a => a.Id == id); 

IEnumerable<Comment> comments = 
    (from c in article.Comments 
    where CommentExpressions.IsApproved.Invoke(c) 
    select c); 


public static class CommentExpressions 
{ 
    public static Expression<Func<Comment, bool>> IsApproved 
    { 
     get 
     { 
      return c => c.IsApproved; 
     } 
    } 
} 

當然,被批准的表達式會更復雜一些。

問題是Invoke()將不起作用,因爲我沒有從container.Comments上的LINQKit調用.asExpandable(),但我無法調用它,因爲它只是一個ICollection而不是ObjectSet。

所以我的問題是:當我想要包含外部表達式時,或者我能以某種方式在我提取的對象(條)上使用它時,是否總是必須經過數據上下文?

任何想法或最佳實踐? 非常感謝! 新

+0

您的意思是「article.Comments」而不是您的示例代碼的第4行中的「container.Comments」? – jeroenh 2010-03-30 10:16:31

+0

哦,是的,謝謝,我糾正了它 – letmaik 2010-03-30 10:36:18

回答

0

當您使用LinqKit使用謂詞建設者:

IEnumerable<Comment> comments = 
    article.Comments.Where(CommentExpressions.IsApproved).Select(c=>c); 

public static class CommentExpressions 
{ 
    public static Expression<Func<Module, bool>> IsApproved 
    { 
     get 
     { 
      var pred = PredicateBuilder.True<Module>(); 
      pred = pred.And(m => m.IsApproved); 
      return pred 
     } 
    } 
} 
+0

不適合我,因爲article.Comments.Where()只接受Func 而不是表達式。 (還有一個錯字,它不是「Module,bool」,而是「Comment,bool」,抱歉) – letmaik 2010-03-30 12:41:52

1

的問題是EF不支持調用的表達式,所以你需要以不同的方式表達到EF倍。

你應該看看達米安的'Client-Side properties'的帖子,它基本上是你要求的。

欲瞭解更多背景信息,請查看Colin Meek的帖子,瞭解如何訪問並替換Invoke expressions with expressions EF can handle

希望這有助於

亞歷

+0

嗯...... Damien的帖子依賴於將「.WithTranslations()」放在表達式的末尾,但這又不是可能在我的情況下,因爲在獲取Article對象後,我沒有得到IQueryable的例如對於article.Comments和.WithTranslations是IQueryable的擴展,這無濟於事。告訴我,如果我忽略了一些東西。 – letmaik 2010-03-31 08:41:26

1

我想我找到了答案,以我的「問題」。我的問題不是真正的問題,而是一種錯誤的思維方式。

當我通讀this時,很明顯我想找到一個解決方案來解決錯誤的問題。讓我解釋一下......

我在EF4上使用POCO模板,並且延遲加載仍然激活。有了這個,我可以奇蹟般地瀏覽這些對象而無需發送額外的查詢,至少它們在我的代碼中不可見。但是,當然,每次訪問關係時都會發送查詢,並且我還使用EF Profiler觀察了這些查詢。當然,我也希望讓他們以最佳方式,即「在sql中使用where條件」而不是「獲取所有行並在之後執行過濾」。這種思維方式也被稱爲過早優化。

當我開始思考「如果我不使用延遲加載會怎麼樣?簡單來說,我想要的所有數據都是在第一時間獲取的,之後您將對這些數據進行操作,並且不進行任何其他操作,即不隱藏查詢。當以這種方式來看待它時,在你的域對象的關係上使用ICollection而不是IQueryable是有意義的。當然,我不能在ICollection上使用Expression>來調用.Where(),而是使用內部函數< ..>。

要回答我自己的問題,表達式<>必須只能在訪問存儲庫或知道它不是POCO對象時使用。如果他們應該在外面使用,即在ICollection的,他們已經被編譯到Func鍵對象那樣:

IEnumerable<Comment> comments = 
    (from c in article.Comments 
    select c).Where(CommentExpressions.IsApproved.Compile()); 

而且如果真的有需要高性能,則庫已被要求獲取所有通過匹配屬於該文章的評論在ID和CommentExpressions.IsApproved完成。類似的東西:

IEnumerable<Comment> comments = 
    (from c in dataContainer.ArticleComments 
    where c.ArticleId == article.Id 
    select c).Where(CommentExpressions.IsApproved); 

現在where條件保留的表達,因爲缺少.compile的(),並可以在SQL中使用的最後一個。

我對此感到滿意。我覺得惱人的是需要調用「.compile()」,我仍然不明白的是如何構建或讓一個表達式使用另一個表達式,除非通過調用.compile()同時包含它,因爲它再次只是ICollection,我無法放置Expression對象。我想在這裏我可以使用LINQKit,然後去掉compile()調用。

我希望我會朝着正確的方向前進。如果您發現任何邏輯錯誤或想到更好的方法,請在評論中告訴我,以便我可以更新答案。謝謝大家!

相關問題