首先,遵循弗兰克施维特曼所说的。让您的存储库随着使用量的增长而增长。此外,了解和使用 IQueryable 接口。L2S,以及实体框架、LINQ to nHibernate,以及一些较新的 ORM,如 SubSonic 和 Telerik 的 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 映射器的真正好处。
如果您更改一种方法,您可以保留原始的、简单的存储库界面,但仍为自己提供很大的灵活性:
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 本身的基本 Repository 类,从而使您无需调用 GetAll() 并直接查询存储库(尽管复杂程度有所不同。)