C# 针对不同数据源混合存储库实现

C# 针对不同数据源混合存储库实现,c#,nhibernate,repository,C#,Nhibernate,Repository,Martin Fowler定义的存储库应该像内存中的域对象集合一样工作。这允许应用程序(理论上)忽略持久性机制 所以在正常情况下,你会有这样的情况: public void MyBusinessLogicMethod () { ... IRepository<Customer> repository = myIocContainer.Resolve<IRepository<Customer>>(); repository.Add(cus

Martin Fowler定义的存储库应该像内存中的域对象集合一样工作。这允许应用程序(理论上)忽略持久性机制

所以在正常情况下,你会有这样的情况:

public void MyBusinessLogicMethod () {
    ...
    IRepository<Customer> repository = myIocContainer.Resolve<IRepository<Customer>>();
    repository.Add(customer);
}
public void MyBusinessLogicMethod(){
...
IRepository repository=myIocContainer.Resolve();
添加(客户);
}
然而,如果您有一系列希望执行的插入/更新,并且希望在任何一个插入/更新失败时有一个回滚机制,则需要某种UnitOfWork实现:

public void MyBusinessLogicMethod () {
    ...
    using (IUnitOfWork uow = new UnitOfWork()){
        IRepository<Customer> customerRepo = myIocContainer.Resolve<IRepository<Customer>>(uow);
        customerRepo.Add(customer); 

        IRepository<Order> orderRepo = myIocContainer.Resolve<IRepository<Order>>(uow);
        orderRepo.Add(order); 

        IRepository<Invoice> invoiceRepo = myIocContainer.Resolve<IRepository<Invoice>>(uow);
        invoiceRepo.Update(invoice);

        uow.Save(); 
    }
}
public void MyBusinessLogicMethod(){
...
使用(IUnitOfWork uow=new UnitOfWork()){
IRepository customerRepo=myIocContainer.Resolve(uow);
customerRepo.Add(客户);
IRepository orderRepo=myIocContainer.Resolve(uow);
orderepo.Add(订单);
IRepository invoiceRepo=myIocContainer.Resolve(uow);
发票更新(发票);
uow.Save();
}
}
但是,如果您有一些奇怪的要求,即客户存储库针对SqlServer数据库、订单存储库针对MySql数据库、发票存储库针对PostgreSQL数据库,您将如何处理每个数据库会话的事务

这确实是一个精心设计的示例,但我遇到的每个存储库实现似乎在某种程度上都知道它实际上是一个特定的数据库和ORM

设想另一个场景,您有两个存储库,其中一个存储库指向数据库,另一个存储库调用web服务。存储库的全部意义在于,应用程序不应该关心您将要使用什么数据源,但如果不跳过一些大的障碍,我不知道如何解释这些场景,而应用程序在某种程度上不知道“仅供参考,这将是数据源x,因此我们最好以不同的方式对待它”


是否有解决此问题的模式或实现?在我看来,如果您在整个应用程序中使用数据库x和ORM y,那么存储库工作得非常出色,但是如果由于技术债务而偏离了这一方向,那么存储库的好处将大大减少。

在您的工作单元中,正如建议的那样,您应该使用TransactionScope事务。
在您的情况下,它提升到MSDTC,并确保在提交或回滚之前正确执行所有登记的操作。

我从来没有理由玩它,但这应该是解决问题的原因。解决方案的一部分是使用而不是
ISession.BeginTransaction()
,但这是我所知道的。是的,TransactionScope是需要考虑的问题。这是一个连接和DbConnection实现,所有提供程序都必须支持两阶段提交。与nhibernate无关,很有趣。是否有一种既定的方法来编写自己的代码,以便由TransactionScope管理?比如说,如果我模拟我的存储库来运行内存中的集合,我可以让它们参与TransactionScope吗?您需要自己编写事务支持。使用内存数据库进行测试,那么您的测试将真正测试查询执行,并且数据库应该实现DTC。