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

时间:2017-02-20 20:27:53

标签: c# entity-framework linq

我有一个Quotes表,它有一个关联的Revisions表。一个基本的业务规则是报价必须至少有一个版本,但可能有很多。我有一个像这样开始的查询...

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

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

这很好,除了我们在数据库中有一个没有任何修订版本的流氓引用。在上面显示的代码下方的某个地方,我得到了一个例外...

  

转换为值类型'System.Int32'失败,因为已实现   value为null。结果类型的泛型参数或查询   必须使用可空类型

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

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

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

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

1 个答案:

答案 0 :(得分:7)

要获得内部联接语义,IMO Select / OrderBy / FirstOrDefault的一般替换为SelectMany / {{1} } / OrderBy

Take(1)