【发布时间】:2009-01-14 21:09:55
【问题描述】:
我对存储库中定义的内容以及留给服务的内容的限制感到困惑。存储库应该只创建与数据库中的表匹配的简单实体,还是可以创建具有这些实体组合的复杂自定义对象?
换句话说:服务是否应该在存储库上进行各种 Linq to SQL 查询?或者所有查询都应该在存储库中预定义,而业务逻辑只是决定调用哪个方法?
【问题讨论】:
标签: asp.net-mvc repository-pattern
我对存储库中定义的内容以及留给服务的内容的限制感到困惑。存储库应该只创建与数据库中的表匹配的简单实体,还是可以创建具有这些实体组合的复杂自定义对象?
换句话说:服务是否应该在存储库上进行各种 Linq to SQL 查询?或者所有查询都应该在存储库中预定义,而业务逻辑只是决定调用哪个方法?
【问题讨论】:
标签: asp.net-mvc repository-pattern
您实际上在这里提出了一个问题,该问题目前在开发者社区中引起了很多讨论 - 请参阅Should my repository expose IQueryable? 的后续 cmets
存储库可以而且应该创建包含多个关联实体的复杂组合对象。在领域驱动设计中,这些被称为聚合 - 相关对象的集合,组织成某种内聚的结构。您的代码不必分别调用GetCustomer()、GetOrdersForCustomer()、GetInvoicesForCustomer() - 您只需调用myCustomerRepository.Load(customerId),就可以返回一个已实例化这些属性的深层客户对象。我还应该补充一点,如果您根据特定的数据库表返回单个对象,那么这是一种完全有效的方法,但它并不是真正的存储库per sé - 它只是一个数据访问层。
一方面,有一个令人信服的论点,即具有“智能”属性和延迟执行(即在您实际使用之前不加载 Customer.Orders)的 Linq-to-SQL 对象是完全有效的存储库模式,因为您实际上并没有在运行数据库代码,而是在运行 LINQ 语句(然后由底层 LINQ 提供程序将其转换为 DB 代码)
另一方面,正如 Matt Briggs 的帖子所指出的,L2S 与您的数据库结构紧密耦合(每个表一个类)并且有局限性(例如,没有多对多映射) - 您可能会更好关闭使用 L2S 在您的存储库内 进行数据访问,然后将 L2S 对象映射到您自己的域模型对象并返回这些对象。
【讨论】:
存储库应该是您的应用程序中唯一了解您的数据访问技术的部分。所以它根本不应该返回由 L2S 生成的对象,而是将这些属性映射到您自己的模型对象。
如果您正在使用这种模式,您可能需要重新考虑 L2S。它为您生成了一个数据访问层,但并不能真正处理阻抗不匹配,您必须手动进行。如果您查看 NHibernate 之类的东西,则该映射是以更健壮的方式完成的。 L2S 更适用于 2 层应用程序,在这种应用程序中,您需要一个可以轻松扩展的快速而肮脏的 DAL。
【讨论】:
如果您使用的是 LINQ,那么我认为存储库应该是您的 LINQ 语法的容器。这使您可以从模型对象接口中对数据库访问例程进行一定程度的抽象。正如上面 Dylan 提到的,对此事还有其他看法,有些人喜欢返回 IQueryable,以便他们可以在存储库之后继续查询数据库。只要您清楚自己的应用程序标准,这两种方法都没有错。 There is more informaiton on the best practices I use for LINQ repositories here.
【讨论】: