我能够使用except运行各种动态组合查询,除非包含子查询。
因此,这不是一个复制的EF核心动态lambda子查询不工作或任何其他我能够找到的事情。
可以在Dotnetfiddle.net/4 4opEqr上找到一个可运行的repro来演示这个问题,它使用一个动态组合的表达式来表示以下查询:
efContext.Products.Where(p => p.Id == efContext.OrderItem.Max(i => i.ProductId)).ToList();我得到的例外是
System.InvalidOperationException : The LINQ expression 'InternalDbSet<OrderItem> { }
.Max(i => i.ProductId)' 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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.我在Microsoft.EntityFrameworkCore.SqlServer中观察到了与Microsoft.EntityFrameworkCore.InMemory相同的行为(版本6.0.8和7.0.0-preview.7.22376.2)。
发布于 2022-09-12 19:36:12
问题似乎既在于EF Core处理表达式树内嵌套可查询表达式的方式,也包括您尝试测试所创建的动态表达式的方式。
很快,这里
productQueryable.Where(p => p.Id == orderItemQueryable.Max(i => i.ProductId))productQueryable是正则变量( .Where是常规调用),orderItemQueryable是编译器生成的闭包(作为可查询的Where谓词表达式的一部分)。
() => productQueryable.Where(p => p.Id == orderItemQueryable.Max(i => i.ProductId))它们都是编译器生成的闭包。
因此,EF不能正确处理在“根”查询表达式中包含嵌套可查询变量值的Constant表达式,因此对于子查询,您应该直接传递IQueryable.Expression属性值,或者模拟闭包(而不是常量)表达式。对于根查询,您应该用常量表达式或模拟闭包(但不是直接)包装它。
因为包装可查询变量对这两种情况都有效,所以解决方案是始终将这些变量封装在闭包模拟表达式中。闭包仿真表达式是指包含常量表达式、保存类实例、在类、属性或字段中保存实际变量的表达式。
它可以通过多种方式实现,例如,使用System.Tuple类作为holder:
static Expression MakeClosure<T>(T value)
{
var closure = new Tuple<T>(value);
return Expression.Property(Expression.Constant(closure), nameof(closure.Item1));
}或者真正的编译器生成闭包类实例:
static Expression MakeClosure<T>(T value)
{
var closure = new { value };
return Expression.Property(Expression.Constant(closure), nameof(closure.value));
}或者使用编译器的主体生成包含闭包的lambda表达式:
static Expression MakeClosure<T>(T value)
{
Expression<Func<T>> lambda = () => value;
return lambda.Body;
}最后,在所有情况下,将示例代码更改为
var productQueryableExp = MakeClosure(productQueryable);
var orderItemQueryableExp = MakeClosure(orderItemQueryable);一切都会如愿以偿。至少有EF核心。您似乎正在使用的另一个库(Remote.Linq)呢?完全不知道(我猜这将是另一个问题)。
https://stackoverflow.com/questions/73690446
复制相似问题