简体   繁体   English

EF 为某些返回 null,但 EF Core 返回 0

[英]EF return null for some but EF Core return 0

I migrate a site ASP.NET MVC to ASP.NET MVC core, with EF to EF Core.我将站点 ASP.NET MVC 迁移到 ASP.NET MVC 核心,使用 EF 到 EF Core。

I make a request with empty value :我提出一个空值的请求:

 var q = bd.Prod
           .Where(o => o.xxx == yyy)
           .GroupBy(o => o.sss)
           .Select(g => new
           {
               ccc = g.Key,
               vvv = g.Sum(i => i.qqq),
               bbb = g.Sum(i => i.fff),
               nnn = g.Sum(i => i.ggg),
           });

When I execute this code with EF return null when all cell of sum are empty.当我使用 EF 执行此代码时,当 sum 的所有单元格都为空时,返回 null。 But EF Core return 0 when all cell of sum are empty.但是当 sum 的所有单元格都为空时,EF Core 返回 0。 How to make EF Core return null ?如何让 EF Core 返回 null ?

Use DefaultIfEmpty :使用DefaultIfEmpty

var q = bd.Prod
          .Where(o => o.xxx == yyy)
          .GroupBy(o => o.sss)
          .Select(g => new
          {
            ccc = g.Key,
            vvv = g.Sum(i => i.qqq),
            bbb = g.Sum(i => i.fff),
            nnn = g.Sum(i => i.ggg),
         })
          .DefaultIfEmpty(null);

If you want the following:如果您想要以下内容:

  • Empty collection -> null空集合 -> null
  • Only null values -> null只有null值 -> null
  • Any combination of numbers and null values -> number数字和null值的任意组合 -> 数字

Try this code:试试这个代码:

items.Aggregate((int?)null, (acc, item) => acc.HasValue ? acc + item.GetValueOrDefault() : item);

Building on @grek40's answer for EF Core 5.0, you can create an extension method so that it can be re-used easily基于@grek40 对 EF Core 5.0 的回答,您可以创建一个扩展方法,以便轻松重用

public static decimal? SumOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
    => (from s in source select selector(s))
       .Aggregate((decimal?)null, (acc, item) => acc.HasValue ? acc + item.GetValueOrDefault() : item);

or if you prefer any nulls to result in a null value或者如果您希望任何空值导致空值

   public static decimal? SumAllOrNull<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
        => (from s in source select selector(s))
           .Aggregate((decimal?)null, (acc, item) => acc.HasValue ? acc + item : item.HasValue ? item : null);

and then call it such as然后调用它,例如

var q = bd.Prod
           .Where(o => o.xxx == yyy)
           .GroupBy(o => o.sss)
           .Select(g => new
           {
               ccc = g.Key,
               vvv = g.SumOrDefault(i => i.qqq),
               bbb = g.SumOrDefault(i => i.fff),
               nnn = g.SumAllOrNull(i => i.ggg),
           });

Note: This only works on Linq-To-Objects, so if on DB query you must call .ToList() or AsIEnumerable before hand, until EF Core supports a way to do this in Linq-To-Sql注意:这仅适用于 Linq-To-Objects,因此如果在 DB 查询中,您必须事先调用 .ToList() 或 AsIEnumerable,直到 EF Core 支持在 Linq-To-Sql 中执行此操作的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM