即使未调用 System.Transactions.TransactionScope.Commit() 也已提交数据

发布于 2024-08-11 05:13:06 字数 299 浏览 9 评论 0原文

在什么情况下,即使抛出了异常并且最外层作用域从未调用过提交,包装在 System.Transactions.TransactionScope 中的代码仍然可以提交?

using (var tx = new TransactionScope()) 包装了一个顶级方法,它以相同的方式调用也使用 TransactionScope 的方法。

我正在使用带有关联表适配器的类型化数据集。适配器中的命令是否由于某种原因未征用?你们中有人知道如何检查他们是否加入了环境 TransactionScope 中吗?

Under what circumstances can code wrapped in a System.Transactions.TransactionScope still commit, even though an exception was thrown and the outermost scope never had commit called?

There is a top-level method wrapped in using (var tx = new TransactionScope()), and that calls methods that also use TransactionScope in the same way.

I'm using typed datasets with associated tableadapters. Could it be that the commands in the adapter aren't enlisting for some reason? Do any of you know how one might check whether they are enlisting in the ambient TransactionScope or not?

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

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

发布评论

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

评论(4

奶茶白久 2024-08-18 05:13:06

答案是因为我在 SqlConnection 对象之后创建了 TransactionScope 对象。

我从这个:

using (new ConnectionScope())
using (var transaction = new TransactionScope())
{
    // Do something that modifies data

    transaction.Complete();
}

转到这个:

using (var transaction = new TransactionScope())
using (new ConnectionScope())
{
    // Do something that modifies data

    transaction.Complete();
}

现在它可以工作了!

因此,这个故事的寓意是首先创建您的 TransactionScope

The answer turned out to be because I was creating the TransactionScope object after the SqlConnection object.

I moved from this:

using (new ConnectionScope())
using (var transaction = new TransactionScope())
{
    // Do something that modifies data

    transaction.Complete();
}

to this:

using (var transaction = new TransactionScope())
using (new ConnectionScope())
{
    // Do something that modifies data

    transaction.Complete();
}

and now it works!

So the moral of the story is to create your TransactionScope first.

何必那么矫情 2024-08-18 05:13:06

明显的情况是显式指定新的 (RequiresNew) / null (Suppress) 事务 - 但也存在超时/解除绑定故障,可能导致连接丢失交易。请参阅此之前的帖子(修复只是连接字符串更改),或完整详细信息

The obvious scenario would be where a new (RequiresNew) / null (Suppress) transaction is explicitly specified - but there is also a timeout/unbinding glitch that can cause connections to miss the transaction. See this earlier post (the fix is just a connection-string change), or full details.

べ映画 2024-08-18 05:13:06

了解 TransactionScope 的工作原理:
它在使用范围开始时设置属性System.Transactions.Transaction.Current,然后在使用范围结束时将其设置回以前的值。

先前的值取决于声明给定范围的位置。它可以在另一个范围内。

您可以这样修改代码:

using (var sqlConnection = new ConnectionScope())
using (var transaction = new TransactionScope())
{
    sqlConnection.EnlistTransaction(System.Transactions.Transaction.Current);
    // Do something that modifies data
    transaction.Complete();
}

我向那些代码更复杂并且不能简单地更改代码以首先打开数据库连接的人展示了这种可能性。

Be aware how TransactionScope works:
It sets property System.Transactions.Transaction.Current at the begining of using scope and then set it back to previous value at end of using scope.

Previous value depends on where given scope is declared. It can be inside another scope.

You can modify code like this:

using (var sqlConnection = new ConnectionScope())
using (var transaction = new TransactionScope())
{
    sqlConnection.EnlistTransaction(System.Transactions.Transaction.Current);
    // Do something that modifies data
    transaction.Complete();
}

I show this possibility for those who have their code more complicated and cannot simply change code to open DB connection first.

尹雨沫 2024-08-18 05:13:06

此示例(C#、.NetFramework 4.7.1)展示了即使代码包装在 TransactionScope 中,我们也可以如何持久保存到数据库。第一个 insert 将回滚,第二个 insert 将在没有事务的情况下插入。

请参阅我的相关帖子,我在其中寻求有关如何检测的帮助这。


using (var transactionScope = new TransactionScope())
{
    using (var connection = new SqlConnection("Server=localhost;Database=TestDB;Trusted_Connection=True"))
    {
        connection.Open();

        new SqlCommand($"INSERT INTO TestTable VALUES('This will be rolled back later')", connection).ExecuteNonQuery();

        var someNestedTransaction = connection.BeginTransaction();
        someNestedTransaction.Rollback();

        new SqlCommand($"INSERT INTO TestTable VALUES('This is not in a transaction, and will be committed')", connection).ExecuteNonQuery();
    }

    throw new Exception("Exiting.");

    transactionScope.Complete();
}

This example (C#, .NetFramework 4.7.1) shows how we can persist to the database even if the code is wrapped in a TransactionScope. The first insert will be rolled back, and the second insert will be inserted without transaction.

See my related post, where I ask for help in how to detect this.


using (var transactionScope = new TransactionScope())
{
    using (var connection = new SqlConnection("Server=localhost;Database=TestDB;Trusted_Connection=True"))
    {
        connection.Open();

        new SqlCommand($"INSERT INTO TestTable VALUES('This will be rolled back later')", connection).ExecuteNonQuery();

        var someNestedTransaction = connection.BeginTransaction();
        someNestedTransaction.Rollback();

        new SqlCommand($"INSERT INTO TestTable VALUES('This is not in a transaction, and will be committed')", connection).ExecuteNonQuery();
    }

    throw new Exception("Exiting.");

    transactionScope.Complete();
}

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