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

时间:2011-08-06 12:07:56

标签: c# .net entity-framework linq lambda

我有这个问题:

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

如果公司8根本没有工人,那么maxShoeSize将会是什么?

更新
如何更改查询以获得0而不是例外?

11 个答案:

答案 0 :(得分:236)

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

DefaultIfEmpty中的零不是必需的。

答案 1 :(得分:47)

我知道这是一个老问题,并且接受的答案有效,但是这个问题回答了我的问题,即这样的空集是否会导致异常或default(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 as

修改
只是为了澄清评论中的内容,Entity Framework目前不支持int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max<[TypeOfWorkers], int?>(x => x.ShoeSize) ?? 0; 关键字,因此在使用EF时编写它的方法是:

[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,但可以对doubleint maxShoeSize = Workers.Where(x => x.CompanyId == 8).MaxOrDefault(x => x.ShoeSize); 或您需要的任何其他值类型执行相同操作。使用这个扩展方法非常简单,你只需传入你的选择器函数,并可选择包含一个用于null的值,默认为0.所以上面的内容可以这样重写:

var _bool = false;
var _box = document.getElementById('box');
var _clik = document.getElementById('clik');

_clik.addEventListener('click', function(){
  if (_bool){
      _box.style.height = '100px';
      _bool = false;
   } else {
      _box.style.height = '10px';
      _bool = true;
   }

});

希望能帮助人们更多。

答案 2 :(得分:26)

在这种情况下,

Max()不会返回任何内容。

由于源不包含任何元素,它将引发InvalidOperationException

答案 3 :(得分:16)

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

答案 4 :(得分:3)

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

(假设ShoeSize的类型为int

如果Workers是来自实体框架的DbSetObjectSet,您的初始查询会抛出InvalidOperationException,但不会抱怨空序列但是抱怨具体化的值NULL无法转换为int

答案 5 :(得分:3)

如果这是Linq to SQL,我不想使用ShoeSize,因为它会导致对SQL服务器的多次查询。

如果.Max(..) ?? 0不是可以为空的字段,那么仅使用int maxShoeSize = Workers.Where(x = >x.CompanyId == 8).Max(x => (int?)x.ShoeSize) ?? 0; 将不起作用,但以下情况将会起作用:

Max()

它绝对不会更改发出的SQL,但如果序列为空则返回0,因为它会更改int?以返回int而不是export default class abc { constructor() { setInterval(() => { service class; }, 30000 ); } }

答案 6 :(得分:2)

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

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;
}

答案 7 :(得分:2)

注意:DefaultIfEmpty()的查询可能会显着。 在我的情况下,这是一个使用.DefaultIfEmpty(DateTime.Now.Date)的简单查询。

我太懒了,但是很明显,EF试图获取所有行,然后取Max()值。

结论:有时处理InvalidOperationException可能是更好的选择。

答案 8 :(得分:0)

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

// assumes Workers != null && Workers.Count() > 0
int maxShoeSize = Workers.Max(x => (x.CompanyId == 8) ? x.ShoeSize : 0);

如果有可能,您需要处理Workers集合为null / empty,但这取决于您的实现。

答案 9 :(得分:0)

你可以试试这个:

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

答案 10 :(得分:0)

在执行Max()之前,您可以检查是否有任何工作人员。

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);
}