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?
而不是intNaor:你听说过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;