我在仓库模式中遗漏了什么?如何在现实世界中使用它
本文关键字:世界 什么 模式 | 更新日期: 2023-09-27 17:48:56
我所看到的存储库模式的每个示例都处理一个非常简单的用例——一个对象类型和最基本的CRUD操作。Repository通常直接插入到MVC控制器中。
真实世界的数据访问不是这样的。真实世界的数据访问场景可能涉及复杂的对象图和某种形式的事务包装器。例如,假设我想保存一个新的Order。这包括写入Order、OrderDetails、Invoice、User、History和ItemStock表。所有这些都必须进行事务处理、提交或回滚。通常我会传递IDbTransaction和IDbConnection之类的东西,并将整个操作捆绑在服务层中。
存储库模式在哪里适合这个?我是不是漏掉了什么(也许是工作单元)?还有比通常的博客片段更实际的使用库的例子吗?
感谢任何光线。
这是一个非常有争议的话题,但这是我从自己的经验中得出的结论。
Repository
工作于聚合根。例如,如果OrderItem
总是作为Order
的一部分被检索,并且没有自己的外部顺序的生命周期,那么它将由OrderRepository
加载,否则它将有自己的存储库。
UnitOfWork
是一个重要的概念。假设OrderItem
是一个聚合根,并且有自己的存储库。因此,在创建订单时,OrderManager
将在using
块中创建UnitOfWork
的工作,初始化OrderItemRepository
和OrderRepository
,然后提交。
是的,没错。想象一下——在我们的例子中是订单——一个订单被插入。这需要控制事务,并在同一事务中分别输入订单和订单项。这不能在存储库级别进行管理。这是UnitOfWork
概念存在的唯一原因,它被传递给存储库,因此它不拥有或初始化它。 UnitOfWork
通常在业务层创建
像Hibernate这样的O/r - mapping基本上实现了对象图的Repository模式,同时完全支持事务。这通常是一个有漏洞的抽象,但它确实可以在复杂的现实场景中工作。
如果您需要一个完整的、广泛使用的存储库模式示例,请查看Cocoa的Core Data,我意识到它不属于您注意到的编程语言领域。但请注意,它不是一个O/R映射器。它是对象存储的完整抽象。没有Sql语句要执行,虽然您可以选择使用的外部存储的格式,但您永远不会直接与它交互。
我喜欢把存储库看作是另一个抽象层。只有当实现抽象层的成本低于不实现抽象层的成本(代码维护、支持、增强等)时,你才应该添加抽象层。
请记住,存储库模式的目的是将检索数据(CRUD)并将其映射到实体模型的逻辑与作用于模型的业务逻辑分离开来。在现实世界中,这样做的结果通常是某种形式的业务实体,它抽象了底层物理数据模型。
就您的事务问题而言,是的,这更多地与工作单元模式有关。既然您提到了服务,我建议您不要将连接传递给各种数据访问类/方法,而是允许WCF使用自动登记为您管理事务。以下是Juval Lowy的WCF书(强烈推荐)的摘录,其中解释了如何以及为什么使用这种事务管理方法。
因此,为了回答您的问题,存储库模式适合作为抽象物理数据模型和将CRUD/映射与业务逻辑分离的一种方式。