在C#异步代码中使用MongoDB ClientSessions和Transactions是否安全?

时间:2018-08-14 10:51:10

标签: c# session transactions async-await mongodb-.net-driver

来自文档Read isolation consistency - Sessions强调我的

  

为提供因果一致性,MongoDB 3.6在客户端会话中启用因果一致性。因果一致的会话表示读取和确认的写操作的关联序列具有因果关系,这由它们的顺序反映出来。 应用程序必须确保一次只有一个线程在客户端会话中执行这些操作

从文档Transactions - Transactions & Sessions

  

交易与会话相关联。也就是说,您开始一个会话的事务。在任何给定时间,一个会话最多可以有一个未完成的事务。

  1. 这是说使用异步/等待是不安全的,还是至少所有使用会话和事务的任务都应该(以某种方式)在同一线程上执行?

  2. 还是说会话上的每个异步操作都需要先完成才能开始另一个异步操作?

  3. 还是说可能有多个异步操作针对该会话运行,但是所有这些操作必须必须在同一线程上运行。

tl; dr
在事务中使用异步/等待是否安全? 如果没有,这里的最佳做法是什么?

例如这是(公认的可怕代码)可以吗?

[HttpPost]
public async Task<IActionResult> PostAsync(CreateRequest createRequest)
{
    using (var session = await _client.StartSessionAsync())
    {
        await session.StartTransactionAsync();

        var inserts = new Task[] {
            _colHomer.InsertOneAsync(session, createRequest.Homer),
            _colMarge.InsertOneAsync(session, createRequest.Marge),
            _colBart.InsertOneAsync(session, createRequest.Bart)
        };

        await Task.WhenAll(inserts);

        await session.CommitTransactionAsync();
    }
}

1 个答案:

答案 0 :(得分:0)

事务和会话designed不是线程安全的。我认为上面的代码可以工作,但不能保证所有情况。 更新:但是以常规异步方式使用会话/事务绝对是省钱的(没有任何手动任务等待和类似的逻辑)。