C# EF核心动态表达式生成器

C# EF核心动态表达式生成器,c#,entity-framework,lambda,C#,Entity Framework,Lambda,我正在尝试建立一个动态EF过滤系统 查询: var query = _db.Promotions.Select(x => new ListPromotionAdminResponseModel() { ActionUrl = x.ActionUrl, Approved = x.Approved, ForShop = x.Shop.Name, Id = x.Id,

我正在尝试建立一个动态EF过滤系统

查询:

        var query = _db.Promotions.Select(x => new ListPromotionAdminResponseModel()
        {
            ActionUrl = x.ActionUrl,
            Approved = x.Approved,
            ForShop = x.Shop.Name,
            Id = x.Id,
            Name = x.Name,
            Categories = x.Categories.Select(y => new CategoryResponseModel() { Id = y.CategoryId, Name = y.Category.Name })
        });
尝试使用过滤器来充实IQueryable

// Works as expected
query = query.Where(x => x.Name == "Name");

// Doesn't work
var parameter = Expression.Parameter(typeof(ListPromotionAdminResponseModel), "x");
MemberExpression member = Expression.Property(parameter, "Name"); ;
query = query.Where(Expression.Lambda<Func<ListPromotionAdminResponseModel
    , bool>>(Expression.Equal(member, Expression.Constant("test")), parameter));
//按预期工作
query=query.Where(x=>x.Name==“Name”);
//不起作用
var parameter=Expression.parameter(typeof(ListPromotionAdminResponseModel),“x”);
MemberExpression member=Expression.Property(参数“Name”);
query=query.Where(Expression.Lambda(Expression.Equal(成员,Expression.Constant(“test”)),参数));
但是,动态表达式不计算预期值,并返回以下异常:

System.InvalidOperationException: The LINQ expression 'DbSet<Promotion>
.Join(
    outer: DbSet<Shop>, 
    inner: p => EF.Property<Nullable<Guid>>(p, "ShopId"), 
    outerKeySelector: s => EF.Property<Nullable<Guid>>(s, "Id"), 
    innerKeySelector: (o, i) => new TransparentIdentifier<Promotion, Shop>(
        Outer = o, 
        Inner = i
    ))
.Where(p => new ListPromotionAdminResponseModel{ 
    ActionUrl = p.Outer.ActionUrl, 
    Approved = p.Outer.Approved, 
    ForShop = p.Inner.Name, 
    Id = p.Outer.Id, 
    Name = p.Outer.Name, 
    Categories = DbSet<CategoryPromotion>
        .Where(c => EF.Property<Nullable<Guid>>(p.Outer, "Id") != null && EF.Property<Nullable<Guid>>(p.Outer, "Id") == EF.Property<Nullable<Guid>>(c, "PromotionId"))
        .Join(
            outer: DbSet<Category>, 
            inner: c => EF.Property<Nullable<int>>(c, "CategoryId"), 
            outerKeySelector: c0 => EF.Property<Nullable<int>>(c0, "Id"), 
            innerKeySelector: (o, i) => new 
                TransparentIdentifier<CategoryPromotion, Category>(
                   Outer = o, 
                   Inner = i
            ))
        .Select(c => new CategoryResponseModel{ 
            Id = c.Outer.CategoryId, 
            Name = c.Inner.Name 
        }
        ) 
}
.Name == "test")' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
System.invalidoOperationException:LINQ表达式“DbSet”
.加入(
外部:DbSet,
内部:p=>EF.Property(p,“ShopId”),
outerKeySelector:s=>EF.Property(s,“Id”),
innerKeySelector:(o,i)=>新的透明标识符(
外部=o,
内部=i
))
.Where(p=>new ListPromotionAdminResponseModel{
ActionUrl=p.Outer.ActionUrl,
批准=p.Outer.Approved,
ForShop=p.Inner.Name,
Id=p.Outer.Id,
Name=p.Outer.Name,
类别=数据库集
其中(c=>EF.Property(p.Outer,“Id”)!=null和&EF.Property(p.Outer,“Id”)==EF.Property(c,“PromotionId”))
.加入(
外部:DbSet,
内部:c=>EF.Property(c,“CategoryId”),
outerKeySelector:c0=>EF.Property(c0,“Id”),
innerKeySelector:(o,i)=>新建
透明剂(
外部=o,
内部=i
))
.Select(c=>newcategoryresponsemodel{
Id=c.Outer.CategoryId,
Name=c.Inner.Name
}
) 
}
.Name==“test”)”无法翻译。以可以翻译的形式重写查询,或者通过插入对AsEnumerable()、AsAsAsAsyncEnumerable()、ToList()或ToListSync()的调用显式切换到客户端计算。看见https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。
例外结束


这两条语句的调试lambda树是相同的。我在这里犯了什么新手错误?

如果执行Where中的部分(不工作的代码)不会引发任何异常,则在评估Where中的“不工作”时会引发异常。InvalidOperationException描述中给出的树由EF和invalid生成。看来这个表达式的位置不对,所以你的问题在中间框中?为什么表达式不像
x.Name==“Name”
?在您的异常中无法找到此部分,它只是以
.Name==“test”)结尾。
无法翻译。这看起来很奇怪。你构建了一个巨大的对象ListPromotionAdminResponseModel,你所做的只是测试它的名称,然后把它扔掉?它没有存储或返回到任何地方。我没有看到任何Where(x=>,其中x是一个ListPromotionAdminResponseModel。也许你的Where(p=>应该是一个Select?我已经更新了这个问题,以澄清第三个框是一个例外。我只想动态地重现'query=query.Where(x=>x.Name==“Name”)“当然,不同的值不同,但为了简单起见,我已将查询的复杂性降至最低。您不能更改操作顺序吗?过滤,强制加载,然后获取结果,而不是(现在)定义结果,过滤,然后加载。因此更改为
\u db.Promotions.Where(expression).ToList()。选择(x=>new ListPromotionAdminResponseModel…
。其中
ToList
是关键部分。