TransactionScope 与 SQLite 内存数据库和 NHibernate

发布于 2024-10-23 23:42:17 字数 1154 浏览 2 评论 0原文

我遇到了一个问题,即使用 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 > 支持似乎不起作用。

I'm running into a problem where a transaction does not roll back when using TransactionScope.

We're using NHibernate with an in memory SQLite database, so that limits us to just one db connection for the duration of the entire lifetime of the application (in this case, some unit tests).

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
}

Even if I remove NHibernate's inner nested transaction so the code is simply as below, the transaction is still commited.

using (var ts = new TransactionScope(TransactionScopeOption.Required, 
                                     TimeSpan.Zero))
{       
    _repository.Save(entity);        
} // no Complete(), but the transaction still commits 

Is it expecting a freshly opened SQLite connection inside the TransactionScope block in order to enlist it in the transaction?

Again, I can't supply it with a new connection because that would clear out the database.

Using NHibernate 3.0 and SQLite 1.0.66.0, both latest versions at the time of writing.

Note: using transaction.Rollback() on the NHibernate ITransaction object correctly rolls back the transaction, it's just the TransactionScope support that doesn't seem to work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

恋竹姑娘 2024-10-30 23:42:17

我想我可能已经找到了原因。如果连接不是从 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

I think I may have found the reason for this. If the connection is not opened from inside the TransactionScope block, it will not be enlisted in the transaction.

There's some information here:
http://msdn.microsoft.com/en-us/library/aa720033(v=vs.71).aspx

Solution:

I already had a .BeginTransaction() method in my repository, so I figured I'd manually enlist the connection in the ambient transaction there.

This is the code I ended up with:

    /// <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();
    }

And here's how I'm using it:

  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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文