簡體   English   中英

實體框架和lambda表達式樹(深度空合並)

[英]Entity Framework and lambda expression tree (deep null coalescing)

var articles = context.Articles.Where(a => a.Id != articleId)
.OrderBy(p => p.Categories.OrderBy(q => q.Name).FirstOrDefault().Name).ToList();

我得到可能的NullReferenceException消息是正確的。

所以我做了

var  articles = context.Articles.Where(a => a.Id != articleId)
                               .OrderBy(p =>
                                   (p.Categories.OrderBy(q => q.Name).FirstOrDefault() != null
                                    ? p.Categories.OrderBy(q => q.Name).FirstOrDefault().Name
                                    : null))
                               .Skip(page * pageSize)
                                  .Take(pageSize)
                                  .ToList();

哪個有效,但聲明是兩次調用,可能很慢,所以我試圖制作

var articles = context.Articles.Where(a => a.Id != articleId)
             .OrderBy(p =>
             {
                 var firstOrDefault = p.Categories.OrderBy(q => q.Name).FirstOrDefault();
                 return firstOrDefault != null ? firstOrDefault.Name : null;
             }).ToList();

但我明白了

具有語句體的lambda表達式無法轉換為表達式樹。

我能做什么? 即使我打了兩次p.Categories.OrderBy(q => q.Name).FirstOrDefault().第一個例子也是正確的p.Categories.OrderBy(q => q.Name).FirstOrDefault().

我在想這可能很慢。 我在數據庫中有200k行。

我得到可能的NullReferenceException消息是正確的。

目前尚不清楚哪個系統正在生成此消息。 ReSharper的?

無論如何,在這種情況下,如果這確實是LINQ to Entities,則警告是虛假的。 LINQ to Entities在許多情況下執行自動“深度空合並”,這就是這種情況。

在您的原始查詢中:

var articles = context.Articles
                      .Where(a => a.Id != articleId)
                      .OrderBy(p => p.Categories
                                     .OrderBy(q => q.Name)
                                     .FirstOrDefault()
                                     .Name)
                       .ToList();

...如果文章沒有與之關聯的類別,則不會出現NullReferenceException 相反,對於這些文章,排序值將被視為null (意味着根本沒有類別的文章將首先出現),它看起來正是您想要的。 因此,您不需要額外的努力!

請注意,對於其他LINQ提供程序(例如LINQ to Objects),行為可能完全不同,而.FirstOrDefault().XXX確實是一個冒險的表達式。

另一方面,不要過早地優化。 如果您已經有一個可行的解決方案,請對其進 如果它太慢,請調查原因 - 在這種情況下,線索在生成的SQL中。 LINQ to Entities查詢優化器通常比您想象的更智能。 :)

您的第二個示例確實會產生更復雜的SQL查詢,但如果此查詢確實會更慢,則由數據庫決定。 無論如何,你可以簡單地改變你的第一個查詢,它應該按預期工作,沒有這個警告:

var articles = context.Articles
                      .Where(a => a.Id != articleId)
                      .OrderBy(p => p.Categories
                                     .OrderBy(q => q.Name)
                                     .Select(q => q.Name)
                                     .FirstOrDefault())
                      .ToList();

查詢中的問題是在調用FirstOrDefault之后選擇Name ,因此如果在調用FirstOrDefault之前投影結果,則不應生成警告,但在結果SQL中將有其他子選擇。

順便說一句。 @Ani的答案是對的。

這似乎是一個重復的答案: “帶有語句體的lambda表達式無法轉換為表達式樹”看起來您不能使用花括號表示的代碼塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM