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

发布于 2024-10-22 12:12:37 字数 751 浏览 2 评论 0 原文

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

假设有一个 Product 实体:

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

    public int UnitsInStock { get; set; }
}

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

IsOnSale = IsDiscontinued == false && UnitsInStock > 0

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

from p in context.Products
where p.IsOnSale == true
select p

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

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

I'd like to know the most maintainable way (if exists) to store an entity condition in a parameter so to reuse it in every linq where conditions.

Suppose to have a Product entity:

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

    public int UnitsInStock { get; set; }
}

I'd like to add to the Product class a property IsOnSale that contains the logic to determine whether the product is on sale or not.
In this simple example the logic could be:

IsOnSale = IsDiscontinued == false && UnitsInStock > 0

Then I should be able to write a linq query of this type:

from p in context.Products
where p.IsOnSale == true
select p

The purpose of the solution should be that, if in the future the logic to determine whether the product is on sale or not changes (e.g. adding a property IsBackOrderAllowed), I don't have to edit the linq queries everywhere but simply have to change the IsOnSale property.

A similar question has been posted here but seems to address a more specific problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

淡淡離愁欲言轉身 2024-10-29 12:12:37

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

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

并且您可以像这样使用它:

from p in context.Products.WhereOnSale()
select p

如果您想使用像 Yakimych 的答案中那样的表达式来执行此操作,那么这将起作用:

Expression<Func<Product, bool>> isOnSale = 
(p => p.IsDiscontinued == false && p.UnitsInStock > 0);

context.Products.Where(isOnSale)

并且您可以像这样使用它 重要的是它被声明为表达式,否则实体框架将无法将其转换为 SQL,因为 lambda 将被编译为 IL 而不是表达式树。

You could make a method that returns an IQueryable filtered by your conditions:

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

and you would use it like this:

from p in context.Products.WhereOnSale()
select p

If you want to do it with an expression like in Yakimych's answer then this would work:

Expression<Func<Product, bool>> isOnSale = 
(p => p.IsDiscontinued == false && p.UnitsInStock > 0);

and you could use it like so:

context.Products.Where(isOnSale)

It is important that it is declared as an expression, otherwise Entity Framework won't be able to translate it into SQL because the lambda will be compiled into IL instead of an Expression Tree.

陌若浮生 2024-10-29 12:12:37

你可以做这样的事情:

Func<Product, bool> isOnSaleFunc = 
                          (p => p.IsDiscontinued == false && p.UnitsInStock > 0);

然后在你的查询中你做:

context.Products.Where(isOnSaleFunc)

更新

作为与@DoctaJonez评论讨论的结果 - 使用这种方法的过滤将在客户端执行(是或当然效率低下),因此应使用 Expression> 而不是 Func

You can do something like this:

Func<Product, bool> isOnSaleFunc = 
                          (p => p.IsDiscontinued == false && p.UnitsInStock > 0);

Then in your query you do:

context.Products.Where(isOnSaleFunc)

Update

As a result of the comment-discussion with @DoctaJonez - the filtering with such an approach will be performed on the client-side (which is or course inefficient), thus Expression<Func<Product, bool>> should be used instead of Func<Product,bool>.

勿忘初心 2024-10-29 12:12:37

这里的第一个问题是 linq to 实体无法使用不属于模型的属性(= 它无法使用自定义属性)。

您必须定义表达式。如果您仅定义 Func ,它将作为 Linq to 对象执行:

public class Product
{
    ...

    public static Expression<Func<Product, bool>> IsOnSale
    {
        get
        {
            return p => (p.IsDiscontinued == false && p.UnitsInStock > 0);
        }
    }
}

现在您必须以这种方式调用查询:

var query = context.Products.Where(Product.IsOnSale);

另一种方法是使用 模型定义函数

First problem here is that linq to entities cannot work with properties which are not part of the model (= it can't work with custom properties).

You must define expression. If you define only Func it will be executed as Linq to objects:

public class Product
{
    ...

    public static Expression<Func<Product, bool>> IsOnSale
    {
        get
        {
            return p => (p.IsDiscontinued == false && p.UnitsInStock > 0);
        }
    }
}

Now you must call the query this way:

var query = context.Products.Where(Product.IsOnSale);

Another approach is using model defined function.

一个人的旅程 2024-10-29 12:12:37

我认为您正在寻找规范模式。

有关将其与 EF 一起使用(包含基本实现)的文章,请访问 http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/

如何实现这一点的一个示例是进行查询

from p in context.Products
where ProductSpecifications.IsOnSale.Predicate
select p

并使用以下帮助程序和规范定义。

public static class ProductSpecifications{
     public static readonly Specification<Product> IsOnSale = new Specification<Product>(x => !x.IsDiscontinued && x.UnitsInStock > 0);  
}

public class Specification<TEntity> : ISpecification<TEntity>
{
    public Specification(Expression<Func<TEntity, bool>> predicate)
    {
        _predicate = predicate;
    }

    public bool IsSatisfiedBy(TEntity entity)
    {
        return _predicate.Compile().Invoke(entity);
    }

    private Expression<Func<TEntity, bool>> _predicate;

    public Expression<Func<TEntity,bool>> Predicate{ 
         get{ return _predicate; }
    }
}

您还可以使用此模式做更多事情,所以我建议您研究一下!

I think you are looking for the Specification Pattern.

An article on using it with EF that includes a base implementation is available at http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/ .

An example of how to implement this would be to make your query

from p in context.Products
where ProductSpecifications.IsOnSale.Predicate
select p

and to use the following helper and specification definition.

public static class ProductSpecifications{
     public static readonly Specification<Product> IsOnSale = new Specification<Product>(x => !x.IsDiscontinued && x.UnitsInStock > 0);  
}

public class Specification<TEntity> : ISpecification<TEntity>
{
    public Specification(Expression<Func<TEntity, bool>> predicate)
    {
        _predicate = predicate;
    }

    public bool IsSatisfiedBy(TEntity entity)
    {
        return _predicate.Compile().Invoke(entity);
    }

    private Expression<Func<TEntity, bool>> _predicate;

    public Expression<Func<TEntity,bool>> Predicate{ 
         get{ return _predicate; }
    }
}

You can do a lot more with this pattern too, so I suggest looking into it!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文