具有多个数据源的工作单元? [英] Unit of Work with multiple Data Sources?

查看:27
本文介绍了具有多个数据源的工作单元?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有可能(甚至很有可能)我只是没有完全理解工作单元"的概念.基本上,我认为它是一种在面向对象环境中使用的广泛事务.启动工作单元,与对象交互,提交或回滚.但这如何分解为这些对象背后的数据存储上的实际事务?

It's possible (even probable) that I'm just not fully grokking the concept of a "unit of work." Basically, I see it as sort of a broad transaction used in an object-oriented environment. Start the unit of work, interact with the objects, commit or roll back. But how does this break down to the actual transactions on the data stores behind those objects?

在具有单个 DB 和 ORM(例如 NHibernate)的系统中,这很容易.事务可以通过 ORM 进行维护.但是对于一个自定义域模型掩盖了许多不同数据源的系统呢?并非所有这些数据源都是关系数据库?(这里的文件系统做了很多工作.)

In a system with a single DB and an ORM (such as NHibernate) it's easy. The transaction can be maintained through the ORM. But what about a system where the custom domain models are obscuring many disparate data sources? And not all of those data sources are relational databases? (There's a lot done on the file system around here.)

现在,我坚持认为您根本无法在同一个‘原子’业务操作中跨 SQL2005 DB、SQL2000 DB、DB2 DB 和文件系统维护事务."因此,目前团队中的开发人员(他们通常彼此独立工作)有责任在代码中手动维护事务.每个 DB 上都可以有适当的事务,但整个业务操作在每个重要步骤都需要人工检查和平衡.

Right now I'm stuck on the idea that "you simply can't maintain a transaction across a SQL2005 DB, a SQL2000 DB, a DB2 DB, and the file system all in the same 'atomic' business operation." So for now it's the responsibility of the developers on the team (who generally work independently of each other) to maintain transactions manually in the code. Each DB can have proper transactions on it, but the business operation as a whole is manually checked and balanced every significant step of the way.

但是,随着域的复杂性和标准开发人员更替率的增加,随着时间的推移,这种方法将变得越来越困难且容易出错.

However, with increasing complexity in the domain and standard developer turnover, this approach will become increasingly difficult and error-prone over time.

有没有人有任何建议或示例说明如何最好地解决此类域,或者以前如何解决?在这种情况下,实际的领域"仍处于起步阶段,作为原型发展到有一天会扩展并消耗/取代由不同的遗留应用程序组成的大型生态系统.因此,有足够的空间进行重新设计和重构.

Does anybody have any advice or examples of how a domain like this might best be addressed, or how it has been addressed before? The actual "domain" in this case is still very much in its infancy, evolving as a prototype to one day expand and consume/replace a large ecosystem of disparate legacy applications. So there's plenty of room for re-designing and re-factoring.

作为参考,我目前的目标设计的 10,000 英尺视图是: 大量小型尽可能愚蠢的客户端应用程序调用中央基于消息的服务.该服务是进入领域核心"的入口,可以被认为是一个大型 MVC 风格的应用程序.向服务发出请求(很像动作"),由处理程序(很像控制器")接收.任何程序都在那里.它们与包含所有业务规则的模型进行交互.模型发布事件,哪些侦听器(服务"?这部分在设计中仍然模糊不清,有待改进)通过与存储库(数据库 x、数据库 y、文件系统、电子邮件、任何外部资源)交互来拾取和处理.一切都相应地进行了依赖注入.

For reference, a 10,000-foot view of the design I'm currently aiming for is: A large collection of small as-dumb-as-possible client applications calling a central message-based service. The service is the entryway into the "domain core" and can be thought of as one big MVC-style application. Requests are made to the service (much like "actions") which are picked up by handlers (much like "controllers"). Anything procedural goes there. They interact with the models, which contain all the business rules. The models publish events which listeners ("services"? this part is still cloudy in the design and subject to improvement) pick up and handle by interacting with repositories (database x, database y, file system, email, any external resource). All merrily dependency-injected accordingly.

抱歉所有的冗长 :) 但是如果有人有任何建议,我很乐意听到.即使(特别是)如果那个建议是你的设计很糟糕,试试这个……"谢谢!

Sorry for all the verbosity :) But if anybody has any advice, I'd love to hear it. Even (especially) if that advice is "your design is bad, try this instead..." Thanks!

推荐答案

我以前研究过一个可以完成此任务的系统,它相当简单.由于您的项目处于早期阶段,因此这可能对您有用.不幸的是,我无法再访问该代码,但仍然可以轻松地描述它的工作原理.

I previously worked on a system that could accomplish this, and it is fairly straightforward. Since you project is in its early stages, perhaps this could be useful information for you. Unfortunately, I no longer have access to the code, but am still comfortable in describing how it worked.

我所做的是使用通用存储库模式实现来构建我的存储库.基本存储库类型将始终是服务和 UoW 的引用.为了便于讨论,我们将其称为 BaseRepository.T"将仅限于表示域对象的 IEntity 实现.从 BaseRepository 中,我创建了另一组用于合成的基类,例如 SqlBaseRepository、XmlBaseRepository 等.

What I had done was built my repositories using a generic repository pattern implementation. The base repository type would always be references by the services and UoW. For sake of discussion, we will call it BaseRepository. "T" would be restricted to IEntity implementations, which denoted a Domain Object. From the BaseRepository, I had created another set of base classes for compositing, such as SqlBaseRepository, XmlBaseRepository, etc.

UoW 只关心 BaseRepository 类型的东西,这是核心功能存在的地方.将表示基本 CUD(CRUD),提供创建、更新和删除的等效项.每一个都会做的是创建一个委托并将它放在 UoW 内的队列中,同时传递有关它将是什么类型的事务的信息,以及完成它所需的适当数据.UoW 将开始维护一个包含哪些存储库需要参与事务的列表,但仍然不关心它是什么类型.实际上,在这里排队就像参加交易一样.

The UoW only cares that something is of the type BaseRepository, which is where the core functionality would exist. Basic CUD (of CRUD) would be represented, providing the equivalents for Creates, Updates, and Deletes. What each of these would do would be to create a delegate and place it in a queue inside the UoW, also passing along information about what type of transaction it was going to be, and the appropriate data required to complete it. The UoW would start maintaining a list of what repositories were going to need to be involved in the transaction, but still did not care what type it was. Effictively, queueing up here is like enlisting in a transaction.

BaseRepository 定义了一个抽象方法,称为 .ApplyChange() 之类的东西.在 UoW 上调用 .Commit() 后,它将创建一个 TransactionScope() 并开始调用列表中的 delagate,将信息传回 .ApplyChange()..ApplyChange() 的实际实现存在于特定的存储库库中,即 SqlRepositoryBase 等,并且也可以被实现覆盖.

The BaseRepository defined an abstract method called something like .ApplyChange(). Once .Commit() was called on the UoW, it would create a TransactionScope() and start calling the delagates in the list, passing back the information to .ApplyChange(). The actual implementation of .ApplyChange() exists in the specific repository base, i.e. the SqlRepositoryBase, etc. and could be overridden by the implementation, as well.

至少对我来说,它变得棘手的地方是回滚.我只处理了一个数据库,但有时会进行基于文件的更改.我添加了一个 .RevertChange() 方法并开始跟踪原始状态和修改后的状态,以便我基本上可以应用反向增量返回到我在文件堆栈上的位置.

Where it got tricky, for me at least, was rolling back. I only dealt with a single database, but sometimes had file-based changes that were made. I added a .RevertChange() method and started tracking the original state and modified states so that I could basically apply a reverse-delta to get back to where I was on the file stack.

我希望我能更具体地说明实现,但我现在已经一年多了.我可以告诉你,原始代码的基础是出自这本书,.NET 域驱动设计与 C#:问题 - 设计 - 解决方案,作者:Tim McCarthy.我的大量代码库实现基于他的示例,而我的大部分自定义都来自 UoW 及其实现.

I wish that I could be more specific on the implementation, but it has been over a year since I have seen the code now. I can tell you that the basis for the original code was borne from the book, .NET Domain-Driven Design with C#: Problem - Design - Solution, by Tim McCarthy. A large amount of my repository implementation was based on his examples, with a large majority of my customization coming in on the UoWs and their implementation.

希望有所帮助!:-)

这篇关于具有多个数据源的工作单元?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆