简体   繁体   English

异步提交或回滚事务范围

[英]Asynchronously commit or rollback a transaction scope

As many knows, TransactionScope were forgotten when the async await pattern was introduced in .Net.众所周知,在 .Net 中引入async await模式时, TransactionScope被遗忘了。 They were broken if we were trying to use some await call inside a transaction scope.如果我们试图在事务范围内使用一些await调用,它们就会被破坏。

Now this is fixed thanks to a scope constructor option .现在,由于范围构造函数选项,此问题已修复。

But it looks to me there is still a missing piece, at least I am unable to find how to do that in a simple "transaction scope like" way: how to await the commit or rollback of a scope?但在我看来仍然缺少一个部分,至少我无法找到如何以简单的“类似事务范围”的方式做到这一点:如何等待范围的提交或回滚?

Commit and rollback are IO operations too, they should be awaitable.提交和回滚也是 IO 操作,它们应该是可等待的。 But since they happen on scope disposal, we have to await the dispose.但由于它们发生在作用域处置上,我们必须等待处置。 That is not doable without having IAsyncDisposable implemented by transaction scopes, which is not currently the case.如果没有事务范围实现IAsyncDisposable ,这是IAsyncDisposable ,目前情况并非如此。

I had a look at the System.Transactions.Transaction interface too: no awaitable methods there either.我也查看了System.Transactions.Transaction接口:那里也没有可等待的方法。

I understand that committing and rollbacking is almost just sending a flag to the database, so it should be fast.我知道提交和回滚几乎只是向数据库发送一个标志,所以它应该很快。 But with distributed transactions, that could be less fast.但是对于分布式事务,这可能会不那么快。 And anyway, that is still some blocking IO.无论如何,这仍然是一些阻塞 IO。

About distributed cases, remember this may trigger a two phases commit.关于分布式案例,请记住这可能会触发两阶段提交。 In some cases additional durable resources are enlisted during the first phase (prepare).在某些情况下,在第一阶段(准备)会征集额外的持久资源。 It then usually means some additional queries are issued against those lately enlisted resources.这通常意味着针对那些最近登记的资源发出一些额外的查询。 All that happening during the commit.在提交期间发生的所有事情。

So is there any way to await a transaction scope?那么有没有办法等待事务范围? Or a System.Transactions.Transaction instead?还是System.Transactions.Transaction代替?

Note: I do not consider this to be a duplicate of " Is it possible to commit/rollback SqlTransaction in asynchronous? ".注意:我不认为这是“是否可以异步提交/回滚 SqlTransaction? ”的重复。 SqlTransaction are more limited than system transactions. SqlTransaction比系统事务更受限制。 They can address only SQL-Server and are never distributed.它们只能寻址 SQL-Server 并且从不分发。 Some other transactions do have async methods, such as Npgsql .其他一些事务确实有异步方法,例如Npgsql Now for having async methods on transaction scopes/system transaction, DbTransaction may be required to have async methods.现在对于事务范围/系统事务具有异步方法,可能需要DbTransaction具有异步方法。 (I do not know the internals of system transaction, but it is maybe using this ADO.NET contract. The way we enlist connection into system transaction does let me think it does not use it though.) (我不知道系统事务的内部结构,但它可能正在使用这个 ADO.NET 合同。我们将连接加入系统事务的方式确实让我认为它并没有使用它。)
Update: DbTransaction does have them in .Net Core 3.0, see #35012 (notably thanks to Roji ).更新: DbTransaction在 .Net Core 3.0 中确实有它们,请参阅#35012 (特别感谢Roji )。

There's no way to implement it so far.到目前为止还没有办法实现它。 But they work on it他们正在努力

Maybe a late answer, but what you want basically boils down to a kind of syntactic sugar that can be easily created on your own.也许是一个迟到的答案,但您想要的基本上归结为一种可以轻松创建的语法糖。

Generalizing your problem, I implemented an "async using" syntax, which allows both the body and the "dispose" part of the "using" to be awaitable.概括您的问题,我实现了“异步使用”语法,它允许“使用”的主体和“处置”部分都可以等待。 Here is how it looks:这是它的外观:

async Task DoSomething()
{ 
    await UsingAsync.Do(
        // this is the disposable usually passed to using(...)
        new TransactionScope(TransactionScopeAsyncFlowOption.Enabled), 
        // this is the body of the using() {...}
        async transaction => {
            await Task.Delay(100);   // do any async stuff here...
            transaction.Complete();  // mark transaction for Commit
        } // <-- the "dispose" part is also awaitable
    );
}

The implementation is as simple as this:实现就像这样简单:

public static class UsingAsync
{
    public static async Task Do<TDisposable>(
        TDisposable disposable, 
        Func<TDisposable, Task> body)
        where TDisposable : IDisposable
    {
        try
        {
            await body(disposable);
        }
        finally
        {
            if (disposable != null)
            {
                await Task.Run(() => disposable.Dispose());
            }
        }
    }
}

There is a difference in error handling, compared to the regular using clause.与常规using子句相比,错误处理有所不同。 When using UsingAsync.Do , any exception thrown by the body or the dispose will be wrapped inside an AggregateException .使用UsingAsync.Do ,主体或处置抛出的任何异常都将包装在AggregateException This is useful when both body and dispose each throw an exception, and both exceptions can be examined in an AggregateException .当 body 和 dispose 都抛出异常时,这很有用,并且可以在AggregateException检查这两个异常。 With the regular using clause, only the exception thrown by dispose will be caught, unless the body is explicitly wrapped in try..catch .使用常规using子句,只会捕获由 dispose 抛出的异常,除非主体显式包含在try..catch

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实体框架6.1中的事务范围回滚 - Transaction scope rollback in Entity Framework 6.1 等待其他事务提交/回滚,然后再开始其他事务? - Wait for other transaction to commit/rollback before beginning another transaction? 在transaction.Commit或Rollback之后连接对象会发生什么 - What happens to connection object after transaction.Commit or Rollback NHibernate事务提交或对象图回滚会抛出“ ObjectDisposedException” - NHibernate transaction commit or rollback for an object graph throws 'ObjectDisposedException' 回滚后提交事务时会发生什么? - What happens when you commit a transaction after rollback? 使用静态数据库连接进行事务提交和回滚c# - Transaction Commit and Rollback with Static DB Connection c# 提交失败时,何时需要回滚NHibernate事务? - When would I need to rollback an NHibernate transaction when it fails on commit? 当其他类在C#中获得结果时,对类进行回滚或提交(企业库事务) - RollBack or Commit (Enterprise Library Transaction) over classes when other class get result in C# 如何启动数据库事务,在MySQL上运行多个查询,然后使用C#提交或回滚? - How to start DB transaction, run multiple queries on MySQL then commit or rollback using c#? C#中的提交和回滚 - Commit And Rollback in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM