最高还是默认?


175

从可能不返回任何行的LINQ查询中获取最大值的最佳方法是什么?如果我只是做

Dim x = (From y In context.MyTable _
         Where y.MyField = value _
         Select y.MyCounter).Max

查询不返回任何行时出现错误。我可以

Dim x = (From y In context.MyTable _
         Where y.MyField = value _
         Select y.MyCounter _
         Order By MyCounter Descending).FirstOrDefault

但这对于这样一个简单的请求来说有点钝。我是否缺少更好的方法?

更新:这是背景故事:我正在尝试从子表中检索下一个资格计数器(旧系统,请不要让我开始...)。每个患者的第一个合格行始终为1,第二个合格行始终为2,依此类推(显然,这不是子表的主键)。因此,我要为患者选择现有的最大计数器值,然后将其添加1以创建新行。当没有现有的子值时,我需要查询返回0(所以加1将使我的计数器值为1)。请注意,我不想依赖子行的原始计数,以防旧版应用程序在计数器值中引入空白(可能)。我很想使这个问题过于笼统。

Answers:


206

由于DefaultIfEmpty未在LINQ to SQL中实现,因此我对返回的错误进行了搜索,发现了一篇引人入胜的文章,涉及聚合函数中的空集。总结一下我发现的内容,可以通过在选择范围内强制转换为null来解决此限制。我的VB有点生锈,但我认为它会像这样:

Dim x = (From y In context.MyTable _
         Where y.MyField = value _
         Select CType(y.MyCounter, Integer?)).Max

或在C#中:

var x = (from y in context.MyTable
         where y.MyField == value
         select (int?)y.MyCounter).Max();

1
若要更正VB,选择应为“选择CType(y.MyCounter,Integer?)”。我必须进行原始检查才能将Nothing转换为0,但是我喜欢毫无例外地获取结果。
gfrizzle

2
LINQ to SQL支持DefaultIfEmpty的两个重载之一-不带参数的重载。
DamienG

可能此信息已过时,因为我刚刚在LINQ to SQL中成功测试了两种形式的DefaultIfEmpty
Neil

3
@Neil:请回答。DefaultIfEmpty对我不起作用:我想要Max一个DateTimeMax(x => (DateTime?)x.TimeStamp)仍然是唯一的方法..
duedl0r 2012年

1
尽管现在已经在LINQ to SQL中实现了DefaultIfEmpty,但此答案在IMO上仍然更好,因为使用DefaultIfEmpty会导致SQL语句“ SELECT MyCounter”返回每个求和值,而此答案导致MAX(MyCounter)返回一个单个汇总行。(已在EntityFrameworkCore 2.1.3中进行了测试)
卡尔·沙曼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.