Linq三元代码更好的解决方案

时间:2015-09-09 13:04:48

标签: c# asp.net entity-framework

我有开发人员写的这段代码。我认为这很可怕而且不一定是必要的

value = s.Businesses.SelectMany(
    x => x.Payments.Where(
        w => w.total != 0 && 
        !w.jobId.HasValue && 
        w.createdAt >= Utility.monthS 
        && w.createdAt <= Utility.monthE)
    ).Any() ? 
        s.Businesses.SelectMany(
            x => x.Payments.Where(
                w => w.total != 0 && 
                !w.jobId.HasValue && 
                w.createdAt >= Utility.monthS 
                && w.createdAt <= Utility.monthE)
            ).Sum(su => su.quantity) 
        : 0;

它在.Any之前执行Sum的原因是没有值的记录最终会获得空值并导致错误。

有没有更好的最佳实践方式来写这个。

2 个答案:

答案 0 :(得分:7)

如果这不适用于Entity Framework,那么Sum只会为空集合返回0,而您不需要执行Any

value = s.Businesses.SelectMany(
    x => x.Payments.Where(
        w => w.total != 0 && 
             !w.jobId.HasValue && 
             w.createdAt >= Utility.monthS && 
             w.createdAt <= Utility.monthE))
    .Sum(su => su.quantity);

但是,由于这是针对实体框架的,因此您将问题变为SQL,而T-SQL中的SUM将返回null以获取空集。因此,您必须使用以下其中一项替换最后一行才能使其正常工作

.Sum(su => (int?)su.quanity) ?? 0;

.Select(su => su.quanity).DefaultIfEmpty().Sum();

第一个将告诉C#期望可能null并且如果它是null则使用0。第二个将使用具有单个默认值的集合替换空结果,在本例中为0。

您不希望Any然后Sum,因为这会导致两次调用数据库。

答案 1 :(得分:1)

这就是查询语法的样子:

var payments = 
  from x in s.Businesses
  from w in x.Payments
  where 
  w.total != 0 && 
  !w.jobId.HasValue && 
  w.createdAt >= Utility.monthS && 
  w.createdAt <= Utility.monthE
  select w;

value = 
payments.Any() ? payments.Sum(p => p.Quantity) : 0;

正如其他海报所评论的那样 - 任何()可能都不是必要的,所以最后一行可能是value = payments.Sum(p => p.Quantity)