TransactionScope与SQLite内存数据库和NHibernate

时间:2011-03-20 15:37:33

标签: unit-testing nhibernate sqlite transactions

我遇到了使用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 transaction.Rollback()对象上使用ITransaction正确回滚事务,这只是TransactionScope支持似乎不起作用。

1 个答案:

答案 0 :(得分: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