[英]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.