C#-实体框架核心:从多个表达式构建一个动态表达式



我有一个名为Product的实体,其中有一个称为ProductAttributes的导航属性。

我需要获得具有多种条件的产品,如:

var products = context.Products
.Include(x => x.ProductAttributes)
.ThenInclude(x => x.Attribute)
.AsNoTracking()
.Where(x => x.ProductAttributes.FirstOrDefault(x => x.AttributeId == attributesIds[0]) != null 
&& x.ProductAttributes.FirstOrDefault(x => x.AttributeId == attributesIds[1]) != null
&& x.ProductAttributes.FirstOrDefault(x => x.AttributeId == attributesIds[2]) != null);

我尝试过动态构建表达式,但所有尝试都失败了。

这是我写的代码:

var arg = Expression.Parameter(typeof(Product), "x");
var left = Expression.Property(arg, "ProductAttributes");
var right = Expression.Constant(null);
var exp = Expression.NotEqual(left, right);
Expression<Func<Product, bool>> expression = Expression.Lambda<Func<Product, bool>>(exp, arg);
foreach (var id in attributesIds)
{
var searchArg = Expression.Parameter(typeof(ProductAttribute), "z");
var searchLeft = Expression.Property(searchArg, "AttributeId");
var searchRight = Expression.Constant(id);
var searchExp = Expression.Equal(searchLeft, searchRight);
Expression<Func<ProductAttribute, bool>> searchExpression = Expression.Lambda<Func<ProductAttribute, bool>>(searchExp, searchArg);
Expression<Func<Product, bool>> subExpression = x => x.ProductAttributes.AsQueryable().Where(searchExpression).FirstOrDefault() != null;
var andExp = Expression.And(expression.Body, subExpression.Body);
expression = Expression.Lambda<Func<Product, bool>>(andExp, arg);
}
var products = context.Products.Include(x => x.ProductAttributes)
.ThenInclude(x => x.Attribute)
.AsNoTracking()
.Where(expression);
// .Where(x => x.ProductAttributes.FirstOrDefault(x => x.AttributeId == attributesIds[0]) != null);
return Ok(products);

我得到的错误是:

无法翻译LINQ表达式"x"。以可翻译的形式重写查询,或者通过插入对"AsEnumerable"、"AsAsyncEnumerable("、"ToList"或"ToListAsync"的调用,显式切换到客户端评估。看见https://go.microsoft.com/fwlink/?linkid=2101038了解更多信息。

那么,如何创建此表达式?或者我的代码出了什么问题?

这还不是一个答案,但我认为你必须构建以下过滤器,它更简单

.Where(x => x.ProductAttributes
.Count(a => attributesIds.Contains(a.AttributeId)) == attributesIds.Length
);

最新更新