首页 > 解决方案 > 如何将运行时参数传递给 EF Core 谓词表达式

问题描述

在使用 EF Core 的应用程序中,我试图通过创建可重用的谓词表达式库来消除查询代码的重复。但是,我正在为接受运行时参数的谓词而苦苦挣扎。

让我们假设父子关系中有 2 个简单的实体类:

public class Parent
{
    public double Salary { get; set; }
    public ICollection<Child> Children { get; set; }

}

public class Child
{
    public double Salary { get; set; }
}

我可以使用像这样的常规 EF Core 查询来检索所有有孩子收入高于他们的父母的父母:

return Context.Set<Parent>()
    .Where(parent => parent.Children.Any(child =>
        child.Salary > parent.Salary));

如果我想为上述查询创建一个可重用的谓词,我想它可能看起来像这样:

private Expression<Func<Child, Parent, bool>> EarnsMoreThanParent = (Child child, Parent parent) => child.Salary > parent.Salary;

上面的谓词编译OK,但我还没有找到任何使用它的方法。问题是如何在运行时将父实体传递给它。这不编译:

return _context.Set<Parent>()
    .Where(parent => parent.Children.Any(child =>
        EarnsMoreThanParent(child, parent));

我知道我将Expression<>andFunc<>语法混为一谈,但我认为这是一个相对常见的要求,必须是可能的。

谢谢

标签: entity-framework-coreexpression-treespredicatebuilder

解决方案


您可以尝试像这样包装整个表达式

private Expression<Func<Parent, bool>> EarnsMoreThanParent = 
    (Parent parent) => parent.Children.Any(child => child.Salary > parent.Salary)

然后用于整个 Where

return _context.Set<Parent>().Where(EarnsMoreThanParent);

你的代码的问题是在.Where(parent => parent.Children.Any(child => EarnsMoreThanParent(child, parent))整个表达式里面是一个表达式。因此,您的方法EarnsMoreThanParent不会被调用,因为它是Where表达式的一部分,EF 会尝试将其解析为表达式并且会失败。

但是,是的,如果您需要将几个这样的条件与不同的条件结合起来,OR它可能无法正常工作,Where(EanrsMoreThanParent).Where(SomeOtherCondition)并且所有这些条件都将被翻译成AND


推荐阅读