如何通过Any函数将父linq表达式与子表达式相结合



我有一个类似的ef模型

public class Parent
{
public int Id { get; set; }
public ICollection<Child> Children{ get; set; }
}
public class Child
{
public int Id { get; set; }
public Parent Parent { get; set; }
public int ParentId { get; set; }
}

我有两个表达式

Expression<Func<Parent,bool>> parentExpression = ...
Expression<Func<Child,bool>> childExpression = ...

我必须像这个一样组合

IQueryable<Parent> queryable = MyParentRepository.All().AsNoTracking();
parentExpression = parentExpression.And(p=>p.Chidlren.Any(c=>childExpression.Compile()(c)); //this is the problem
var results = queryable = queryable.Where(parentExpression).ToList();

And()Expression<Func<T, bool>>的一种扩展方法,它已经在中工作

但是当ef核心转换可查询时,我获得了错误

The LINQ expression 'DbSet<Child> ....' 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.

有没有一种方法可以在不编译childExpression的情况下组合表达式?

提前感谢

EDIT(找到可能的解决方案(

由于IQueryable.Any需要一个表达式,与IEnumerable.Any需要一个Func不同,我尝试了这种方法,它可以工作

IQueryable<Parent> queryable = MyParentRepository.All().AsNoTracking();
parentExpression = parentExpression.And(p=>p.Chidlren.AsQueryable().Any(childExpression); //<----
var results = queryable = queryable.Where(parentExpression).ToList();

不幸的是,EF的故事很长。如果没有额外的扩展,它将无法工作。

这个问题的流行答案是LINQKit,因为我知道最新版本应该处理Compile()

IQueryable<Parent> queryable = MyParentRepository.All()
.AsExpandable() // important call
.AsNoTracking();

那么您的查询应该可以工作了。

此外,LINQKit还为Invoke提供了另一个选项。别忘了打电话给AsExpandable

parentExpression = parentExpression
.And(p => p.Chidlren.Any(c => childExpression.Invoke(c));

正如我在问题上所写的,由于IQueryable.Any采用表达式作为自变量,与IEnumerable.Any采用Func不同,我尝试了这个

IQueryable<Parent> queryable = MyParentRepository.All().AsNoTracking();
parentExpression = parentExpression.And(p=>p.Chidlren.AsQueryable().Any(childExpression); //<----
var results = queryable = queryable.Where(parentExpression).ToList();

它工作完美,显然没有缺点

最新更新