EF Core查询中使用Let抛出“参数类型不匹配”异常的解决咨询
解决EF Core 2.0.1中查询最新订单时的表达式异常问题
兄弟,这个问题我太熟了——EF Core 2.0.1版本对LastOrDefault()的LINQ表达式翻译支持有明显局限,尤其是你在查询里结合三元运算符处理空值的时候,很容易触发表达式树构建失败的异常。本质上是因为这个版本还没办法把LastOrDefault()的结果和后续的空值判断完整转换成SQL语句。
给你两个可行的解决方案,优先选第一个:
方案一:用OrderByDescending + FirstOrDefault()替代LastOrDefault()
EF Core对FirstOrDefault()的翻译支持要稳定得多,我们只需要把订单按日期倒序排列,取第一个就是最新的订单,完全可以达到和LastOrDefault()一样的效果,还能避免异常。修改后的查询代码如下:
(from u in DbContext.User.Where(u => u.UserId == userId) let lastOrder = u.Orders.OrderByDescending(o => o.Date).FirstOrDefault() select new UserDto { Id = u.Id, Name = u.Name, LastOrderId = lastOrder?.Id, LastOrderDate = lastOrder?.Date }) .FirstOrDefault();
这里我还用了C#的空值传播运算符?.替代了你的三元运算符,代码更简洁,而且EF Core 2.0.1也能正确把这个转换成SQL的空值判断逻辑。
方案二:先加载用户及订单到内存再处理(不推荐大数据量)
如果因为某些限制必须用LastOrDefault(),可以先把用户和关联的订单全部加载到内存,再在客户端处理最新订单。但要注意,这样会把该用户的所有订单都拉到内存里,数据量大的时候性能会很差:
var user = DbContext.User.Where(u => u.UserId == userId) .Include(u => u.Orders) .FirstOrDefault(); if (user == null) return null; var lastOrder = user.Orders.LastOrDefault(); var userDto = new UserDto { Id = user.Id, Name = user.Name, LastOrderId = lastOrder?.Id, LastOrderDate = lastOrder?.Date };
最后提一句:EF Core 2.0.1是比较老旧的版本了,很多LINQ翻译的bug在后续3.x、5.x及以上版本都被修复了,如果项目允许的话,升级到更高版本能避免很多这类奇怪的问题。
内容的提问来源于stack exchange,提问作者SajithK
相关产品推荐
相关产品推荐

