C# 如果查询为空,则返回最大值

C# 如果查询为空,则返回最大值,c#,.net,entity-framework,linq,lambda,C#,.net,Entity Framework,Linq,Lambda,我有一个疑问: int maxShoeSize = Workers .Where(x => x.CompanyId == 8) .Max(x => x.ShoeSize); 如果8号公司根本没有员工,那么maxShoeSize中会有什么内容 更新: 如何更改查询以获取0而不是异常?在这种情况下不会返回任何内容 它将引发,因为源不包含任何元素。Max将抛出System.InvalidOperationException“序列不包含任何元素” 类程序 { 静态void

我有一个疑问:

int maxShoeSize = Workers
    .Where(x => x.CompanyId == 8)
    .Max(x => x.ShoeSize);
如果8号公司根本没有员工,那么maxShoeSize中会有什么内容

更新:
如何更改查询以获取0而不是异常?

在这种情况下不会返回任何内容


它将引发,因为源不包含任何元素。

Max将抛出System.InvalidOperationException“序列不包含任何元素”

类程序
{
静态void Main(字符串[]参数)
{
列表=新列表();
添加(新的MyClass(){Value=2});
IEnumerable迭代器=list.Where(x=>x.Value==3);//空迭代器。
int max=iterator.max(x=>x.Value);//抛出System.InvalidOperationException
}
}
类MyClass
{
公共价值观;
}
(假设
ShoeSize
类型为
int

如果
Workers
是实体框架中的
DbSet
ObjectSet
,则初始查询将抛出
invalidooperationexception
,但不会抱怨空序列,而是抱怨物化值NULL无法转换为
int

int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                     .Select(x => x.ShoeSize)
                     .DefaultIfEmpty()
                     .Max();

DefaultIfEmpty
中的零是不必要的。

NB:使用
DefaultIfEmpty()
的查询可能会明显慢一些。 在我的例子中,这是一个带有
.DefaultIfEmpty(DateTime.Now.Date)
的简单查询

我懒得分析它,但显然EF试图获取所有行,然后获取
Max()


结论:有时处理
无效操作异常
可能是更好的选择。

我知道这是一个老问题,公认的答案有效,但这个问题回答了我的问题,即这样的空集是否会导致异常或
默认(int)
结果

然而,公认的答案虽然有效,但不是理想的解决方案,这里没有给出。因此,我在我自己的答案中提供它,是为了任何正在寻找它的人的利益

OP的原始代码是:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize);
我将这样编写它以防止异常并提供默认结果:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize as int?) ?? 0;
这导致
Max
函数的返回类型为
int?
,它允许
null
结果,然后
null
结果替换为
0


编辑
仅从评论中澄清一点,Entity Framework目前不支持
as
关键字,因此在使用EF时编写它的方法是:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max<[TypeOfWorkers], int?>(x => x.ShoeSize) ?? 0;
这只处理
int
,但对
long
double
或任何其他您需要的值类型也可以这样做。使用此扩展方法非常简单,只需传入选择器函数,并可选地包含一个用于null的值,该值默认为0。因此,上述内容可以改写如下:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).MaxOrDefault(x => x.ShoeSize);

希望这对人们的帮助更大。

您可以使用
.Max()中的三元谓词来处理谓词并设置其值

// assumes Workers != null && Workers.Count() > 0
int maxShoeSize = Workers.Max(x => (x.CompanyId == 8) ? x.ShoeSize : 0);
如果可能的话,您需要处理
Workers
集合为null/empty,但这取决于您的实现。

您可以尝试以下方法:

int maxShoeSize = Workers.Where(x=>x.CompanyId == 8).Max(x => x.ShoeSize) ?? 0;

在执行Max()之前,您可以检查是否有工人

private int FindMaxShoeSize(IList工作者){
var workersInCompany=workers.Where(x=>x.CompanyId==8);
如果(!workersInCompany.Any()){return 0;}
返回workersInCompany.Max(x=>x.ShoeSize);
}

如果这是Linq to SQL,我不喜欢使用
Any()
,因为它会导致对SQL server的多个查询

如果
ShoeSize
不是可为空的字段,则仅使用
.Max(..)??0将不起作用,但以下各项将起作用:

int maxShoeSize = Workers.Where(x = >x.CompanyId == 8).Max(x => (int?)x.ShoeSize) ?? 0;

它绝对不会更改发出的SQL,但是如果序列为空,它会返回0,因为它更改了
Max()
返回一个
int?
而不是
int

Naor:你听说过LINQPad吗?我不明白如果你已经尝试过,为什么你会问“maxShoeSize
中会有什么内容?”。@jwg:我想看看你是否知道答案:)最终我找到了一个更好的方法来完成我的要求,这就是我想要的“我是说,@Naor,这不是猜谜游戏。我也会否决原来的问题。如果你知道答案给我们,否则你看起来很懒。刚才我正要问同样的问题,我准备了所有的信息,包括异常消息。很好的解决方案!更流行的
DefaultIfEmpty
答案只有在
Max
没有进行计算时才有效。@McGuireV10是的,我通常不喜欢在结果上使用像
Max
这样的聚合函数时使用
Select
作为中间人。我还认为(我还没有对此进行测试)生成的SQL将通过这样做使用额外的subselect查询,而我的SQL将通过返回null来处理空集。感谢您的投票和反馈!;)@McGuireV10类似地,如果
ShoeSize
实际上在一个相关的
Uniform
实体中,我不会使用
Workers.Where(x=>x.CompanyId==8)。选择(x=>x.Uniform.Max(x=>x.ShoeSize)
,而是将整个计算结果保存在
Max
函数中:
Workers.Where(x=>x.CompanyId==8)。Max(x=>x.Uniform.ShoeSize)
。我更喜欢在查询中使用尽可能少的方法,以使EF在决定如何有效地构造查询时拥有最大的自由度;-)我无法在EntityFramework中实现这一点。有人能解释一下吗?(使用DefaultIfEmpty技术有效)。扩展方法的通用版本:
publicstatictresultmaxOrdefault(此IQueryable项,表达式选择器,tresultDefaultValue=default),其中TResult:struct=>items.Select(selector).Max(item=>(TResul
int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                     .Select(x => x.ShoeSize)
                     .DefaultIfEmpty()
                     .Max();
// assumes Workers != null && Workers.Count() > 0
int maxShoeSize = Workers.Max(x => (x.CompanyId == 8) ? x.ShoeSize : 0);
int maxShoeSize = Workers.Where(x=>x.CompanyId == 8).Max(x => x.ShoeSize) ?? 0;
private int FindMaxShoeSize(IList<MyClass> workers) {
   var workersInCompany = workers.Where(x => x.CompanyId == 8);
   if(!workersInCompany.Any()) { return 0; }
   return workersInCompany.Max(x => x.ShoeSize);
}
int maxShoeSize = Workers.Where(x = >x.CompanyId == 8).Max(x => (int?)x.ShoeSize) ?? 0;