使用SQLite内存数据库和NHibernate的TransactionScope

4

我遇到了一个问题,使用TransactionScope时,事务没有回滚。

我们正在使用NHibernate和内存中的SQLite数据库,因此在应用程序的整个生命周期(在这种情况下是一些单元测试)中,我们只能使用一个数据库连接。

using (var ts = new TransactionScope(TransactionScopeOption.Required, 
                                     TimeSpan.Zero))
{
    using (var transaction = _repository.BeginTransaction())
    {
        _repository.Save(entity);
        transaction.Commit();
    }
    // ts.Complete(); <- commented Complete call still commits transaction
}

即使我去掉NHibernate的嵌套事务,使代码仅为下面这样,事务仍然被提交。
using (var ts = new TransactionScope(TransactionScopeOption.Required, 
                                     TimeSpan.Zero))
{       
    _repository.Save(entity);        
} // no Complete(), but the transaction still commits 

TransactionScope块内部,它是否期望一个新打开的SQLite连接以便将其加入事务?但是,我无法提供新连接,因为那样会清空数据库。使用NHibernate 3.0和SQLite 1.0.66.0,这两个版本都是最新的。请注意,在NHibernate ITransaction对象上使用transaction.Rollback()可以正确回滚事务,只是TransactionScope支持似乎不起作用。

SQLite(及其驱动程序)是否支持分布式事务,或者它是否明确了TransactionScope? - Diego Mijelshon
@diego:是的,根据SQLite ADO.NET提供程序论坛上的帖子,TransactionScope已经支持了几年。 "自动分布式事务登记"也是他们主页上指出的功能之一。 - andreialecu
在作用域结束后检查,数据是否被持久化? - Diego Mijelshon
1个回答

1

我认为我可能已经找到了原因。如果连接没有从TransactionScope块内部打开,它将不会被注册到事务中。

这里有一些信息: http://msdn.microsoft.com/en-us/library/aa720033(v=vs.71).aspx

解决方案:

我已经在我的存储库中有一个.BeginTransaction()方法,所以我想手动将连接注册到环境事务中。

这是我最终使用的代码:

    /// <summary>
    /// Begins an explicit transaction.
    /// </summary>
    /// <returns></returns>
    public ITransaction BeginTransaction()
    {
        if (System.Transactions.Transaction.Current != null)
        {
            ((DbConnection) Session.Connection).EnlistTransaction(System.Transactions.Transaction.Current);
        }
        return Session.BeginTransaction();
    }

这是我如何使用它的方式:

  using (var ts = new TransactionScope(TransactionScopeOption.Required, TimeSpan.Zero))
  using (var transaction = repository.BeginTransaction())
  {
       repository.Save(entity);
       transaction.Commit(); // nhibernate transaction is commited
        // ts.Complete(); // TransactionScope is not commited
  } // transaction is correctly rolled back now

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接