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().
我在想这可能很慢。我在数据库中有200k行。
答案 0 :(得分:4)
我收到可能的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查询优化器通常比您想象的更智能。 :)
答案 1 :(得分:2)
你的第二个例子确实会产生更复杂的SQL查询,但是如果这个查询真的会慢一些,那就是数据库了。无论如何,你可以简单地改变你的第一个查询,它应该按预期工作,没有那个警告:
var articles = context.Articles
.Where(a => a.Id != articleId)
.OrderBy(p => p.Categories
.OrderBy(q => q.Name)
.Select(q => q.Name)
.FirstOrDefault())
.ToList();
您的查询中的问题是在您致电Name
后选择FirstOrDefault
,因此如果您在致电FirstOrDefault
之前预测结果,则不会产生警告,但会有其他子选择结果SQL。
顺便说一下。 @ Ani的回答是正确的。
答案 2 :(得分:0)
这似乎是一个重复的答案:"A lambda expression with a statement body cannot be converted to an expression tree"您似乎无法使用花括号表示的代码块。