我有这个查询:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
maxShoeSize
如果公司8根本没有工人,那将会是什么?
更新:
如何更改查询以获取0而不是异常?
maxShoeSize
?” 如果您已经尝试过。
我有这个查询:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
maxShoeSize
如果公司8根本没有工人,那将会是什么?
更新:
如何更改查询以获取0而不是异常?
maxShoeSize
?” 如果您已经尝试过。
Answers:
int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
.Select(x => x.ShoeSize)
.DefaultIfEmpty(0)
.Max();
零输入DefaultIfEmpty
不是必需的。
我知道这是一个古老的问题,可以接受的答案有效,但是这个问题回答了我有关这样一个空集是导致异常还是default(int)
结果的问题。
但是,虽然可以接受,但是可以接受的答案不是IMHO的理想解决方案,此处未给出。因此,我以自己的答案提供它,以帮助正在寻找它的任何人。
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
。
编辑
只是为了澄清注释中的内容,实体框架当前不支持该as
关键字,因此在使用EF时编写该关键字的方式为:
int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max<[TypeOfWorkers], int?>(x => x.ShoeSize) ?? 0;
由于[TypeOfWorkers]
可能是一个很长的类名,并且编写起来很繁琐,所以我添加了扩展方法来提供帮助。
public static int MaxOrDefault<T>(this IQueryable<T> source, Expression<Func<T, int?>> selector, int nullValue = 0)
{
return source.Max(selector) ?? nullValue;
}
这只手柄int
,但同样可以为完成long
,double
或任何其他价值,你需要的类型。使用此扩展方法非常简单,只需传入选择器函数,并可以选择包含要用于null的值(默认为0)。因此,可以将上述内容重写为:
int maxShoeSize = Workers.Where(x => x.CompanyId == 8).MaxOrDefault(x => x.ShoeSize);
希望这可以帮助人们更多。
DefaultIfEmpty
仅当Max
不进行评估时,比较流行的答案才有效。
Select
当我将要使用类似Max
结果的聚合函数时,我通常不喜欢用作中间人。我还认为(我尚未测试过)生成的SQL将通过执行此操作使用额外的子选择查询,而我的SQL只会通过返回null来处理空集。感谢您的支持和反馈!;)
ShoeSize
实际位于相关Uniform
实体中,则不使用Workers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
,而是将整个求值保留在Max
函数中:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
。我更喜欢在查询中使用尽可能少的方法,以使EF在决定如何有效构造查询时拥有最大的自由度。;-)
public static TResult MaxOrDefault<TElement, TResult>(this IQueryable<TElement> items, Expression<Func<TElement, TResult>> selector, TResult defaultValue = default) where TResult : struct => items.Select(selector).Max(item => (TResult?)item) ?? defaultValue;
在这种情况下,Max()将不会返回任何内容。
由于源不包含任何元素,因此将引发InvalidOperationException。
InvalidOperationException
:如果列表中的对象是一个非可空类型docs.microsoft.com/en-us/dotnet/api/...
Max将抛出System.InvalidOperationException“序列不包含任何元素”
class Program
{
static void Main(string[] args)
{
List<MyClass> list = new List<MyClass>();
list.Add(new MyClass() { Value = 2 });
IEnumerable<MyClass> iterator = list.Where(x => x.Value == 3); // empty iterator.
int max = iterator.Max(x => x.Value); // throws System.InvalidOperationException
}
}
class MyClass
{
public int Value;
}