MVC:仓储库和服务

5

我对仓库定义的限制和应该留给服务的内容感到困惑。仓库只能创建与数据库中表匹配的简单实体,还是可以创建由这些实体组合而成的复杂自定义对象?

换句话说:服务是否应该在仓库上进行各种 Linq to SQL 查询?还是所有查询都应该在仓库中预定义,业务逻辑只需决定调用哪个方法?

3个回答

11

你提出的问题目前正在开发者社区中引起广泛讨论 - 参见Should my repository expose IQueryable? 的后续评论。

仓储库可以 - 也应该 - 创建包含多个关联实体的复杂组合对象。在领域驱动设计中,这些被称为聚合根 - 关联对象的集合,组织成某种有凝聚力的结构。你的代码不需要分别调用GetCustomer()GetOrdersForCustomer()GetInvoicesForCustomer(),只需调用myCustomerRepository.Load(customerId),就会返回一个深层次的客户对象,其中这些属性已经被初始化了。我还要补充一点,如果你是基于特定数据库表返回单独对象,那么这是一种完全有效的方法,但它并不是真正的仓储库 per sé - 它只是一个数据访问层。

一方面,有一个有说服力的观点认为,Linq-to-SQL 对象具有“智能”属性和延迟执行(即不会加载 Customer.Orders,直到你实际使用它)等特点,因此是仓储库模式的完全有效实现,因为你实际上并没有运行数据库代码,而是运行 LINQ 语句(然后由底层的 LINQ 提供程序将其转换为 DB 代码)。

另一方面,正如 Matt Briggs 的帖子指出的那样,L2S 与您的数据库结构相当紧密地耦合在一起(每个表一个类),并且有一些限制(例如,没有多对多映射) - 因此,您可能最好在仓储库中使用 L2S 进行数据访问,但然后将 L2S 对象映射到自己的领域模型对象并返回这些对象。


2

一个仓库应该是应用程序中唯一知道数据访问技术的部分。因此,它不应该返回由L2S生成的对象,而是将这些属性映射到您自己的模型对象。

如果您正在使用这种模式,您可能需要重新考虑L2S。它为您生成了一个数据访问层,但并没有真正处理阻抗不匹配,您必须手动处理。如果您查看类似NHibernate的东西,那么这种映射是以更强大的方式完成的。 L2S更适合于两层应用程序,其中您需要一个快速且简单的DAL,可以轻松扩展。


2
如果您正在使用LINQ,那么我的信仰是存储库应该是您的LINQ语法的容器。这为您提供了从模型对象接口中抽象出数据库访问例程的级别。正如Dylan在上面提到的,对此问题有其他观点,有些人喜欢返回IQueryable,以便他们可以在存储库之后的某个时候继续查询数据库。无论采用哪种方法,只要您清楚应用程序的标准即可。这里有更多我用于LINQ存储库的最佳实践信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接