当应用于IQueryable <T>时,Expression.Constant会舍弃现有的WHERE条件

时间:2019-07-09 12:48:12

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

上下文

我有一个IQueryable扩展方法GetAllGroupedBy,该方法应该通过EF Core解决MySQL上的每组最大n个问题。

基本上它构造了这种类型

public struct OrderedGroupItem<TModel, TKey>
{
    public TKey GroupKey { get; set; }
    public int OrderKey { get; set; }
    public TModel Value { get; set; }
}

通过对表中的每个元素进行内部计数,以给定的顺序在该元素下面有多少个元素。

该代码长100行,可以在here中找到。

问题

在扩展方法中传递IQueryable<T>查询时,调试器将显示:

value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[Persistence.Models.Project])
        .Where(...)

因为extensions方法的调用方式如下:

query.Where(...).GetAllGroupedBy(...);

因此,传入的query正确存储了Where(...)调用之前的GetAllGroupedBy部分。

但是当我然后通过Expression.Constant(query)将其放在表达式中时,得到的表达式是:

{
    new OrderedGroupItem`2() 
    {
        GroupKey = Invoke(x => x.GroupKey, x), 
        OrderKey = value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[Type])
            .Where(y => 
                (Invoke(x => x.GroupKey, x) 
                    == Invoke(x => x.GroupKey, y))
            )
            .Where(y => 
                Invoke((x, y) => 
                    (
                        (Compare(x.OrderValue, y.OrderValue) < 0) 
                        OrElse (
                            (Compare(x.OrderValue, y.OrderValue) == 0) 
                            AndAlso (x.Id < y.Id)
                        )
                    ), 
                    x, 
                    y
                )
            ).Count(), 
        Value = x
    }
}

并且翻译后的SQL不会重复原始的.Where(...)过滤器。

问题

为什么Expression.Constant(queryable)删除了可查询条件中存储的.Where(...)条件?我在做什么错了?

1 个答案:

答案 0 :(得分:1)

代替:

Expression.Constant(query)

您应该使用:

query.Expression