【问题标题】:TransactionScope with SQLite in-memory database and NHibernateTransactionScope 与 SQLite 内存数据库和 NHibernate
【发布时间】:2011-03-20 15:37:32
【问题描述】:

我遇到了使用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:是的,根据 SQLite ADO.NET 提供者论坛上的帖子,TransactionScope 已经支持几年了。 “自动分布式事务登记”也是他们主页上注明的功能之一。
  • 如果在范围结束后检查,数据是否持久化?

标签: unit-testing nhibernate sqlite transactions


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多