Met*_*eny 8 c# transactions unit-of-work repository-pattern mongodb
我正在使用“存储库+工作单元”模式在C#Mongo DB驱动程序的顶部实现DAL抽象层。我当前的设计是每个工作实例实例都将打开(和关闭)新的Mongo DB会话。问题是Mongo DB仅允许会话和事务之间的1:1比率,因此在同一.NET事务下无法进行多个工作单元。
当前的实现是:
public class MongoUnitOfWork
{
private IClientSessionHandle _sessionHandle;
public MongoUnitOfWork(MongoClient mongoClient)
{
_sessionHandle = mongoClient.StartSession();
}
public void Dispose()
{
if (_sessionHandle != null)
{
// Must commit transaction, since the session is closing
if (Transaction.Current != null)
_sessionHandle.CommitTransaction();
_sessionHandle.Dispose();
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,以下代码将不起作用。第一批数据将提前提交:
using (var transactionScope = new TransactionScope())
{
using (var unitOfWork = CreateUnitOfWork())
{
//... insert items
unitOfWork.SaveChanges();
} // Mongo DB unit of work implementation will commit the changes when disposed
// Do other things
using (var unitOfWork = CreateUnitOfWork())
{
//... insert some more items
unitOfWork.SaveChanges();
}
transactionScope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
显然,直接的答案是将所有更改整合到一个工作单元中,但这并不总是可能的,而且这也泄漏了Mongo DB的局限性。
我考虑过会话池,以便多个工作单元将使用同一会话,并在临时事务完成/中止时提交/回滚。
还有哪些其他解决方案?
澄清:
这里的问题专门涉及使用MongoDB 4.0(或更高版本)内置事务支持在MongoDB上实现工作单元。
我从未使用过MongoDB;一无所知。我只是在回答TransactionScope
; 所以不确定这是否对您有帮助。
请参考TransactionScope的魔力。IMO,您应该寻找三个因素:
连接到数据库应该打开里面的TransactionScope
。
因此请记住,必须在TransactionScope块内打开该连接才能使其自动加入环境事务中。如果在此之前打开了连接,则它将不参与事务。
不确定,但是看起来您可以使用手动注册在范围之外打开的连接connection.EnlistTransaction(Transaction.Current)
。
查看您的评论和编辑,这不是问题。
所有操作应在同一线程上运行。
所提供的环境事务
TransactionScope
是线程静态(TLS)变量。可以使用静态Transaction.Current
属性进行访问。这是TransactionScope
referencesource.microsoft.com 上的代码。ThreadStatic ContextData,包含CurrentTransaction
。
和
请记住,Transaction.Current是线程静态变量。如果您的代码在多线程环境中执行,则可能需要采取一些预防措施。必须参与环境事务的连接必须在创建管理该环境事务的TransactionScope的同一线程上打开。
因此,所有操作应在同一线程上运行。
根据需要使用TransactionScopeOption
(将其传递到的TransactionScope
)构造函数值。
TransactionScope
通过该new
语句实例化a时,事务管理器确定要参与的事务。确定后,作用域始终参与该事务。该决定基于两个因素:是否存在环境事务以及TransactionScopeOption
构造函数中参数的值。
我不确定您的代码应该做什么。您可以使用此枚举值。
如评论中所述,您正在使用async/await
。
最后,如果您在TransactionScope块内使用async / await,则应该知道它不能与TransactionScope一起很好地工作,并且您可能想研究.NET Framework 4.5.1中接受TransactionScopeAsyncFlowOption的新TransactionScope构造函数。TransactionScopeAsyncFlowOption.Enabled选项(不是默认选项)允许TransactionScope在异步继续中正常运行。
对于MongoDB,请查看这是否对您有帮助。
归档时间: |
|
查看次数: |
516 次 |
最近记录: |