我想知道在参数中存储实体条件的最可维护方式(如果存在),以便在条件中的每个linq中重用它。
假设有一个产品实体:
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属性。
类似的问题已发布here,但似乎解决了一个更具体的问题。
答案 0 :(得分:2)
您可以这样做:
Func<Product, bool> isOnSaleFunc =
(p => p.IsDiscontinued == false && p.UnitsInStock > 0);
然后在您的查询中执行:
context.Products.Where(isOnSaleFunc)
<强>更新强>
作为与@DoctaJonez的评论讨论的结果 - 使用这种方法的过滤将在客户端执行(这或者当然效率低下),因此应该使用Expression<Func<Product, bool>>
而不是{{} 1}}。
答案 1 :(得分:1)
您可以创建一个方法,返回根据您的条件筛选的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而不是表达式树。
答案 2 :(得分:1)
这里的第一个问题是linq to entities不能使用不属于模型的属性(=它不能用于自定义属性)。
您必须定义表达式。如果仅定义Func
,它将作为Linq执行到对象:
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);
另一种方法是使用model defined function。
答案 3 :(得分:0)
我认为您正在寻找规范模式。
http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/提供了一篇关于在EF中使用它的文章,其中包含一个基本实现。
如何实现这一点的一个例子是进行查询
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; }
}
}
你也可以用这种模式做更多的事情,所以我建议调查一下!