在会话中执行命令而不将其传递给每个命令

时间:2019-05-28 10:16:03

标签: c# mongodb transactions

在我的应用程序中,我使用存储库模式,并且希望能够在与事务的会话中执行存储库(或多个存储库)中的某些方法。 它应该是可选的,因此有时我想添加用户而不使用事务,但是在其他地方我想在会话和事务中执行相同的方法。 我不想使用可选的IClientSessionHandle参数在每个存储库方法上创建重载,这对我来说听起来很丑。

我试图像在Entity Framework中一样实现基本的工作单元模式。我拥有但无法正常工作的代码如下:

using (var uow = _uowProvider.Create())
{
     repository.Add(someEntity);   
     repository.Add(otherEntity);
     uow.Commit(); //just calls CommitTransaction on wrapped session
}

此示例中的“ uow”仅包装了IClientSessionHandle,我希望如果我从该会话中创建集合,它们将被包含在它及其事务中,但不包括在内。

在IUnitOfWorkProvider内部,我实例化集合(简化),如下所示:

_unitOfWorkProvider.Current == null
                       ? collection
                       : _unitOfWorkProvider.Current.Session.Client.GetDatabase(collection.Database.DatabaseNamespace.DatabaseName)
                           .GetCollection<T>(collection.CollectionNamespace.CollectionName);

结果是,我的命令(如InsertOneAsync等)不在会话中执行,因为我没有将会话对象传递给他们。如果我通过空会话,则该调用(因为会话/事务是可选的)将引发NRE。

是否有一种方法可以选择在mongo集合上执行命令,而无需将会话实例显式传递给它们?

1 个答案:

答案 0 :(得分:1)

查看MongoDB.Entities的源代码以了解其如何解决此问题。最终结果是交易代码如下:

    using (var TN = new Transaction())
    {
         var author1 = new Author { Name = "one" };
         var author2 = new Author { Name = "two" };

         TN.Save(author1);
         TN.Save(author2);

         TN.Commit();
         }
    }