加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何重写此Linq查询以避免使用FirstOrDefault?

发布时间:2020-12-15 23:37:50 所属栏目:百科 来源:网络整理
导读:我有一个Quotes表,它有一个相关的Revisions表.一个基本的业务规则是报价必须至少有一个版本,但可能有很多.我有一个像这样开始的查询…… var revisions = ctx.Quotes .Select(q = q.Revisions.OrderByDescending(r = r.RevisionNumber).FirstOrDefault()) //
我有一个Quotes表,它有一个相关的Revisions表.一个基本的业务规则是报价必须至少有一个版本,但可能有很多.我有一个像这样开始的查询……

var revisions = ctx.Quotes
  .Select(q => q.Revisions.OrderByDescending(r => r.RevisionNumber).FirstOrDefault())
  // Do things with the revisions here...

目的是获取每个引用的最新版本,然后从中选择一些信息.

这样可以正常工作,除了我们在数据库中有一个没有任何修订的流氓引用.在上面显示的代码下方的某处,我得到了一个例外……

The cast to value type ‘System.Int32’ failed because the materialized
value is null. Either the result type’s generic parameter or the query
must use a nullable type

这花了一个时间来调试,因为我们没有意识到它是由流氓引用引起的.理想情况下,查询的第二行将使用First()而不是FirstOrDefault(),它会在那里抛出异常,立即显示问题的根源.但是,Entity Framework不允许您使用First()或Single()mid-query,这就是我们使用FirstOrDefault()的原因.

没有完全重写查询,即首先查询Revisions表并导航回到Quote(由于其他原因会很痛苦),是否有一种简单的方法来防范这种情况?在这种情况下,我通过将第一行更改为…来修复它

var revisions = ctx.Quotes.Where(q => q.Revisions.Any())

…但这是针对这种情况的具体修复,并且在我们最终发现问题后才明显.理想情况下,我想要一个通常适用的解决方案.

解决方法

要获得内连接语义,IMO一般替换Select / OrderBy / FirstOrDefault是SelectMany / OrderBy / Take(1):

var revisions = ctx.Quotes
    .SelectMany(q => q.Revisions.OrderByDescending(r => r.RevisionNumber).Take(1))
    // Do things with the revisions here...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读