为什么在此查询中“ IQueryable.Where()”提供的结果与“ IEnumerable.Where()”不同?

Fra*_*k B 3 c# linq entity-framework entity-framework-core

我正在尝试使用linq从EF Core数据集中过滤某些行,但我不明白为什么过滤IEnumerable与过滤IQueryable会给我带来不同的结果。

        var query = _db.Jobs
            .IsDelivered()
            .Include(a => a.JobExtras)
            .Include(a => a.Tips)
            .Include(a => a.Payments)
            .HasPayments();

        var query1 = query
            .ToList()
            .Where(a => a.Payments.Sum(b => b.Amount)
                         - a.Price.Value
                         - a.Discount
                         - a.JobExtras.Sum(c => c.Price)
                         - a.Tips.Sum(d => d.Amount)
                         > 0);

        var query2 = query
           .Where(a => a.Payments.Sum(b => b.Amount)
                         - a.Price.Value
                         - a.Discount
                         - a.JobExtras.Sum(c => c.Price)
                         - a.Tips.Sum(d => d.Amount)
                         > 0);

        Debug.WriteLine($"Record Count[Before Where Clause]: {query.Count()}");
        Debug.WriteLine($"Record Count[ToList() version]: {query1.Count()}");
        Debug.WriteLine($"Record Count[w/out ToList()]: {query2.Count()}");
Run Code Online (Sandbox Code Playgroud)

这是输出:

Record Count[Before Where Clause]: 8379
Record Count[ToList() version]: 5921
Record Count[w/out ToList()]: 0
Run Code Online (Sandbox Code Playgroud)

为什么IEnumerable版本产生5921条记录,而IQueryable版本产生0条记录?

Kit*_*Kit 5

第一个查询使用.NET类型和在内存中执行Enumerable.Sum()。传递的所有null都将Sum被跳过,因此您的某些数据正在通过> 0测试。

第二个查询在数据库中执行并使用SQL的SUM。如果Where子句中表达式的任何部分包含空值,则该表达式的值将为空。null > 0在SQL中,采用该表达式并将其进行比较()始终将其评估为false,因此将过滤所有行。

您的第二个查询可能是可修复的。我不知道这一点,因为我不知道您的模型(即,什么可以为空),并且不确定EF是否可以翻译此模型:

.Where(a => a.Payments.Where(x => x != null).Sum(b => b.Amount)
     - a.Price.Value
     - a.Discount
     - a.JobExtras.Where(x => x != null).Sum(c => c.Price)
     - a.Tips.Where(x => x != null).Sum(d => d.Amount)
     > 0);
Run Code Online (Sandbox Code Playgroud)