首先,遵循Frank Schwieterman所说的。让你的存储库随着它们的使用而增长。此外,了解并利用IQueryable接口。 L2S以及Entity Framework,LINQ to nHibernate和一些新的ORM(如SubSonic和Telerik's ORM)都支持IQueryable接口。
在需要可变查询但仍希望获得必要的OR映射器互换好处的情况下,IQueryable是一个强大的工具。假设像以下这样的东西:
public class ProductRepository: IProductRepository
{
public Product GetByID(int id);
public IList<Product> GetAll();
public void Insert(Product product);
public Product Update(Product product);
public void Delete(Product product);
}
这是一个非常常见的存储库,具有基本的通用方法。随着时间的推移,您可能会拥有更多的方法:
public IList<Product> GetByOrder(Order order);
public IList<Product> GetByCategory(Category category);
public IList<Product> GetByQuantityInStock(int quantityInStock);
这也是相当普遍的情况,根据你喜欢解决问题的方式,它是完全可以接受的。然而,从长远来看,你的代码库可能会变得难以控制,并且其接口将始终在变化。你还会失去使用OR mapper的真正好处。
如果你改变一个方法,你可以保持原始简单的代码库接口,但仍然为自己提供很多灵活性:
public IQueryable<Product> GetAll();
您的代码库现在返回一个查询而不是已检索对象的列表。现在您可以像使用任何其他LINQ启用的对象一样使用此查询:
var productsWithLowStock = productRepository.GetAll().Where(p => p.Quantity < 10);
var orders = orderRepository.GetAll();
var productsWithOrders = productRepository.GetAll().Where(p => orders.OrderLines.Any(ol => ol.ProductID == p.ProductID));
一旦您开始使用IQueryable接口与您的仓储库一起,您将获得最佳效果:在较低级别的数据访问周围具有可模拟抽象,并且可以在代码中动态查询的能力。您可以将此概念推广一步,并创建一个基础仓储库类,它实现了IQueryable本身,允许您消除GetAll()调用的需要,并直接查询存储库(尽管有另一种复杂程度)。