工作单元:由服务层或存储库层创建/管理? C#/.NET
我一直在阅读,现在已经看到了工作单元模式的两种不同实现。第一种模式让存储库与工作单元和域对象进行通信。
另一个实现具有将域对象注册为修改后的服务层:
我想我的问题是,每个都有什么好处/缺点?我知道如果不为存储库/映射器/等提供一些实现代码,就有很多问题需要回答...但总的来说,谁/什么应该真正负责“更新”UoW 然后使用它?
我的想法是,如果你让存储库处理它,它应该作为存储库的可注入接口提供,以便同一个 UoW 可以跨越多个存储库(也称为多个域对象)...
如果服务层处理它,那么您就会“陷入”每个服务层调用只有一个 UoW 实现的困境(例如,ServiceLayer.AddCustomer(customer))。
在网络世界中,我看不到为不同的域对象调用多个服务层......但也许在非网络世界中我可以。
我想某些东西最终必须调用“commit()”,因此将其绑定到服务层是最有意义的。
谢谢, 麦克风
I'm been reading, and have now seen two different implementations of the Unit of Work pattern. The first pattern has the Repository talking to the Unit of Work to a domain object.
The other implementation has the Service layer registering the domain object as modified:
I guess my question is, what are the benefits/drawbacks to each? I know that is lot to answer without providing some implementation code for the repositories/mappers/etc... but in general, who/what should really be responsible for "newing up" the UoW and then working with it?
My thought is if you let the Repository handle it, it should be provided as a injectable interface to the repository(s) so the same UoW can span multiple repositories (aka, multiple domain objects)...
If the service layer handles it, then you're kind of "stuck" with only one UoW implementation per Service Layer call (example, ServiceLayer.AddCustomer(customer)).
In the web world, I can't see multiple service layers being called for different domain objects... but maybe in the non-web world I can.
I imagine something eventually has to call "commit()", so it makes the most sense to have that tied into the Service Layer.
Thanks,
Mike
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
与使用存储库相比,向客户端公开 UoW 通常是对存储实现的更强大的抽象,因为语义是基于状态的,而不是显式的“加载/保存/删除”操作。另一方面,明确性允许客户端通过使用规范等更好地控制在线实际发生的情况。IMO
没有“正确”的方法,选择最合适的模式实际上取决于应用程序的数据流和持久层限制。
一些想法 -
存储库通常管理单个聚合根,而 UoW 可以覆盖多个聚合根。
理想情况下,UoW 应该是持久不可知的(因为它主要处理对象状态,例如更改跟踪)。您的映射器显然将根据您的存储实现进行定制。但是其他存储问题/责任在哪里得到解决?存储库通常就是这个问题的答案。
存储库模式可以更轻松地使用专门的语义(通过添加新方法)扩展存储解决方案,或调整内部实现(例如在某些情况下调用存储过程而不是动态代码)
对于具有直接和同质存储需求的应用程序,直接公开 UoW 可能是一种选择一个更简单的模型。对于更复杂的环境(例如动态 SQL 和存储过程的混合使用、遗留模式等),存储库更具可维护性和可扩展性,但代价是使用时受到更多限制。
这是我的头顶上的事情,希望它能有所帮助......
Exposing the UoW to clients is typically a stronger abstraction over the storage implementation than using a Repository since the semantics are state-based instead of explicit "load/save/delete" actions. On the other hand, explicitness allows clients greater control over what really happens over-the-wire through use of specifications etc.
IMO there is no "correct" approach, choosing the most appropriate pattern really depends on the application's data flows and the persistance layer constraints.
A few thoughts-
A Repository typically manages a single aggreggate root, while a UoW can cover multiple.
Ideally, the UoW should be persistant-agnostic (since it deals mostly with object state such as change tracking). Your mapper will obviously be tailored to your storage implementation. But where are the other storage concerns/responsibilities addressed? The Repository is usually the answer to that.
Repository pattern makes it easier to extend the storage solution with specialized semantics (by adding new methods), or tweaking internal implementations (for example calling a sproc in certain scenarios instead on dynamic code)
For an application with straighforward and homogenous storage requirements, directly exposing the UoW is a probably a simpler model. For more complex environments (such as mixed usage of dynamic SQL and sprocs, legacy schemas, et) then Repository is more maintainable and extensible, at the cost of being a bit more restrictive to use.
This is off the top of my head, hope it helps...
即使在第一个实例中,您的 UnitOfWork 很可能是单例(每个线程),因此即使 CustomerRepository 和 OtherBoilerplateExampleRepository 在调用提交之前都访问 UnitOfWork,提交仍将使用所有存储库所做的所有更改。
话虽这么说,我认为第一种模式是更干净的方法。对于第二种方式,您是说 CustomerService 必须操作业务对象并且向 UnitOfWork 注册更改。这有点违反了关注点分离。此外,这些示例中未显示,但存储库模式也提供了缓存数据对象的位置。
就注入依赖项而言,我认为与其使 UoW 成为可注入接口,不如使 Mapper 模式(您在第二个示例中看到,但可能在第一个示例中隐含)可注入是更合适的选择。无论您是否使用 SQL DB、XML 文件等,UoW 事务管理功能都应该保持不变。
Even in the first instance, your UnitOfWork will most likely be a singleton (per thread), so that even if a CustomerRepository and OtherBoilerplateExampleRepository both access the UnitOfWork before a commit is called, a commit will still use all changes made by all repositories.
That being said, I think the first pattern is the cleaner way of doing it. With the second way you're saying that the CustomerService has to both manipulate business objects and register the changes with the UnitOfWork. That violates separation of concerns a bit. Also, not shown in these examples, but the Repository pattern provides a place to cache data objects, as well.
As far as injecting dependencies, I think rather than making the UoW an injectable interface, making the Mapper pattern (that you see in the second example but is presumably implied in the first) injectable is the more appropriate choice. No matter if you're working with an SQL DB, XML file, etc., the UoW transaction management functions should stay the same.