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