我有一个使用LINQ的存储库来建模数据,该数据包含大量用于获取数据的函数。获取数据的一种非常常见的方法是下拉列表等。这些下拉列表可能会有所不同。如果我们正在创建一些东西,我们通常会有一个下拉列表,其中包含某些类型的所有条目,这意味着我需要一个按实体类型过滤的函数。我们还有用于过滤数据的页面,下拉列表仅包含当前使用的条目,因此我需要一个需要使用条目的过滤器。这意味着有六种不同的查询可以获得相同类型的数据。
为每个定义一个函数的问题是,至少对于每种类型的输出都有六个函数,所有这些都在一个存储库中。它变得非常大,非常快。这就像我打算做的那样:
public IEnumerable<Supplier> ListSuppliers(bool areInUse, bool includeAllOption, int contractTypeID)
{
if (areInUse && includeAllOption)
{
}
else if (areInUse)
{
}
else if (includeAllOption)
{
}
}
虽然“areInUse”看起来并不是非常友好,但我对命名并不精彩。如您所见,逻辑驻留在我的数据访问层(存储库)中,这是不友好的。我可以定义单独的功能,但正如我所说,它增长得非常快。
有人可以推荐一个好的解决方案吗?
注意:我只使用LINQ for 实体,我不用它来查询。请不要问,这是对我未指定的系统的约束。如果我有选择,我会使用LINQ,但不幸的是我没有。
答案 0 :(得分:3)
让您的方法采用可在Where子句中使用的Func<Supplier,bool>
,以便您可以在任何类型的过滤器中传递它而不是您想要构造的过滤器。您可以使用PredicateBuilder根据布尔运算构造任意复杂的函数。
public IEnumerable<Supplier> ListSuppliers( Func<Supplier,bool> filter )
{
return this.DataContext.Suppliers.Where( filter );
}
var filter = PredicateBuilder.False<Supplier>();
filter = filter.Or( s => s.IsInUse ).Or( s => s.ContractTypeID == 3 );
var suppliers = repository.ListSuppliers( filter );
答案 1 :(得分:0)
您可以实施
IEnumerable<Supplier> GetAllSuppliers() { ... }
然后在返回的集合上使用LINQ。这将从数据库中检索所有供应商,然后使用LINQ进行过滤。
假设您正在使用LINQ to SQL,您还可以实现
IQueryable<Supplier> GetAllSuppliers() { ... }
然后在返回的集合上使用LINQ。这只会在枚举集合时从数据库中检索必要的供应商。这非常强大,您可以使用的LINQ也有一些限制。但是,最大的问题是您可以使用LINQ直接钻取数据访问层并进入数据库。
像
这样的查询var query = from supplier in repository.GetAllSuppliers()
where suppliers.Name.StartsWith("Foo") select supplier;
在枚举时将映射到与此类似的SQL
SELECT ... WHERE Name LIKE 'Foo%'