如何在属性中存储 Linq where 条件

Edo*_*doT 5 c# linq entity-framework expression-trees

我想知道将实体条件存储在参数中的最可维护的方法(如果存在),以便在每个 linq where 条件中重用它。

假设有一个 Product 实体:

public class Product
{
    public bool IsDiscontinued { get; set; }

    public int UnitsInStock { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想向 Product 类添加一个属性 IsOnSale,其中包含确定产品是否促销的逻辑。在这个简单的例子中,逻辑可以是:

IsOnSale = IsDiscontinued == false && UnitsInStock > 0
Run Code Online (Sandbox Code Playgroud)

然后我应该能够编写这种类型的 linq 查询:

from p in context.Products
where p.IsOnSale == true
select p
Run Code Online (Sandbox Code Playgroud)

该解决方案的目的应该是,如果将来确定产品是否在销售的逻辑发生变化(例如添加属性 IsBackOrderAllowed),我不必到处编辑 linq 查询,而只需更改IsOnSale 属性。

此处已发布类似的问题,但似乎解决了更具体的问题。

Rei*_*ica 7

您可以创建一个返回按您的条件过滤的 IQueryable 的方法:

public IQueryable<Product> WhereOnSale(this IQueryable<Product> source)
{
    return source.Where(p => p.IsDiscontinued == false && p.UnitsInStock > 0);
}
Run Code Online (Sandbox Code Playgroud)

你会这样使用它:

from p in context.Products.WhereOnSale()
select p
Run Code Online (Sandbox Code Playgroud)

如果你想用 Yakimych 的答案中的表达式来做到这一点,那么这会起作用:

Expression<Func<Product, bool>> isOnSale = 
(p => p.IsDiscontinued == false && p.UnitsInStock > 0);
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

context.Products.Where(isOnSale)
Run Code Online (Sandbox Code Playgroud)

将其声明为表达式很重要,否则实体框架将无法将其转换为 SQL,因为 lambda 将被编译为 IL 而不是表达式树。