0

由于我继承了一个代码库,我有一个相当奇怪的要求。DAL 基于存储库模式,但是一些存储库是使用带有直接 SQL 和参数化查询的 SqlConnection/SqlCommand 编码的,有些是使用 NHibernate 编码的。

我需要执行一系列数据操作,这需要来自两个分区的存储库,如果它在沿途的任何阶段失败,它都需要回滚。解决此问题的最佳方法是什么?

System.Data 公开了一个 IDbTransaction 和 NHibernate 一个 ITransaction,这两者是否兼容?如果出现问题,我可以同时运行两个事务然后将它们都回滚吗?TransactionScope 在这种情况下会帮助我吗?

4

3 回答 3

1

TransactionScope 将创建一个挂钩,所有通过 ADO.Net 的组件都将遵守该挂钩。由于所有ORM 都通过 ADO.Net,它们都将隐含地尊重 TransactionScope。像 NHibernate、Linq、EF 或您选择的任何 ORM 之类的代码都无法抑制这种情况,除非它们通过用新范围显式覆盖当前范围来显式抑制 TransactionScope。

问题可能是由于多个连接注册到服务器上,事务升级为服务器上的分布式事务。这是一个很棘手的主题,受 SQL Server/.Net 版本的影响,请参阅System.Transactions 与 SQL Server 的集成

于 2012-10-05T14:19:48.917 回答
1

nhibernate也支持sql语句

我好像记得方法

NHibernateSession.CreateSQLQuery,它返回IQuery(实际上是SQLQuery

你可以继续调用方法ListUniteResult

通常,编码人员喜欢使用名为Hashtable的 kv 类

您可以在 Nhibernate 中使用 ITransaction。

于 2012-10-05T13:50:45.913 回答
1

我假设您希望拥有类似于以下的代码:

public class SomeService
{
    private readonly IRepositoryA _repoA;
    private readonly IRepositoryB _repoB;

    public void DoStuff(EntityA someEntityA, EntityB someEntityB)
    {
        try 
        {
             _repoA.Save(someEntityA);
             _repoB.Save(someEntityB);
             // commit all stuff here

        }
        catch
        {
             // rollback all stuff here
        }
    }
}

如果确实如此,那么您需要有某种 UnitOfWork 抽象,这两个存储库都依赖并且可以引用它们各自的事务上下文。如果两个 repos 都使用 Nhibernate 或 IDbConnection/DbTransactions 会容易得多,但由于存在混合,您将不得不做更多的工作。

您需要创建一个包含 IDbTransaction 和 ITransaction 的“GenericTransaction”,并让您的工作单元拥有一个创建新 GenericTransaction 的方法。

GenericTransaction 上的提交/回滚将对两个事务执行相应的操作。

要做到这一点,您将不得不对现有的存储库进行相当多的重构......但我不会推荐任何其他方式。

于 2012-10-05T14:21:03.390 回答