C# 我应该在下面代码的哪一行提交我的工作单元?
我有一个事务中的以下代码。我不确定我应该在哪里/什么时候提交我的工作单元 我特意没有提到我使用的是哪种类型的呼吸——例如Linq到Sql、实体框架4、NHibernate等等 如果有人知道在哪里,他们能解释一下为什么他们会说,在哪里?(我试图通过示例来理解模式,而不仅仅是让代码正常工作) 以下是我得到的:-C# 我应该在下面代码的哪一行提交我的工作单元?,c#,.net,transactions,unit-of-work,C#,.net,Transactions,Unit Of Work,我有一个事务中的以下代码。我不确定我应该在哪里/什么时候提交我的工作单元 我特意没有提到我使用的是哪种类型的呼吸——例如Linq到Sql、实体框架4、NHibernate等等 如果有人知道在哪里,他们能解释一下为什么他们会说,在哪里?(我试图通过示例来理解模式,而不仅仅是让代码正常工作) 以下是我得到的:- using ( TransactionScope transactionScope = new TransactionScope (
using
(
TransactionScope transactionScope =
new TransactionScope
(
TransactionScopeOption.RequiresNew,
new TransactionOptions
{ IsolationLevel = IsolationLevel.ReadUncommitted }
)
)
{
_logEntryRepository.InsertOrUpdate(logEntry);
//_unitOfWork.Commit(); // Here, commit #1 ?
// Now, if this log entry was a NewConnection or an LostConnection,
// then we need to make sure we update the ConnectedClients.
if (logEntry.EventType == EventType.NewConnection)
{
_connectedClientRepository.Insert(
new ConnectedClient { LogEntryId = logEntry.LogEntryId });
//_unitOfWork.Commit(); // Here, commit #2 ?
}
// A (PB) BanKick does _NOT_ register a lost connection,
// so we need to make sure we handle those scenario's as a LostConnection.
if (logEntry.EventType == EventType.LostConnection ||
logEntry.EventType == EventType.BanKick)
{
_connectedClientRepository.Delete(
logEntry.ClientName, logEntry.ClientIpAndPort);
//_unitOfWork.Commit(); // Here, commit #3 ?
}
_unitOfWork.Commit(); // Here, commit #4 ?
transactionScope.Complete();
}
对所有存储库执行所有操作后,在#4提交。如果您事先提交,则在该调用之后所做的更改不会提交。假设您的数据存储正在分配ID,您必须提交#1(使用NHibernate,您甚至应该刷新),然后在#4结尾。回答这个问题的一个很好的起点是从企业架构模式中定义工作单元(): 维护受业务事务影响的对象列表,并协调更改的写出和并发问题的解决 工作单元的边界是由业务事务的边界定义的——在本例中,它与数据库事务的边界同义(但在跨多个请求的长时间运行的业务事务中,情况可能并非如此) 从上面的定义向后操作,并基于我对所示代码的理解,您应该在业务事务结束时提交工作单元(#4)
另外,数据库事务作用域应始终小于UoW的作用域(即,tx作用域位于对UoW.Begin()和UoW.Commit()的调用之间)。如果您的UoW跨越多个数据库事务,那么如果其中一个内部事务失败,您将使用补偿事务来“重新平衡”UoW。在这种情况下,尤其是如果您的UoW正在UoW.Begin()和UoW.Commit()创建自己的数据库事务边界,我会删除事务范围,因为这只是给代码添加了不必要的干扰。我认为您应该让工作单元处理事务……我假设您的UoW知道TransactionScope。它应该根据您提交事务的时间知道何时提交自己。这当然取决于
\u unitOfWork
的声明位置?@Mark Seemann@Ryan:Hmm.(我的)工作单元不知道事务。应该吗?指向某些.NET代码的示例链接?Linq到sql?EF?尼伯酸盐@丹·普泽伊:为什么?因为我们假设你的工作单元纯粹是为了处理这笔交易而创建的。此事务可以是较大工作单元的较小部分。我们也不知道UoW的实现是什么——从您的评论来看,您可能已经自己实现了它。在这种情况下,理解您的实现可能是回答您的问题的关键:-)也许我遗漏了什么。代码后面是否再次调用了_unitOfWork.Commit()?可能我们的困惑在于UoW是否具有事务感知能力,因此何时/是否调用Commit()并不重要。否则,如果它不支持事务,并且存储库绑定到UoW,并且不会再次调用Commit(),则work将只修改存储库中在调用Commit()之前而不是之后更改的内容。我刚刚确认UoW支持事务->它创建自己的读取提交事务,所以我不需要做我的。现在这完全有100%的意义了:)提交启动一个tran,执行所有更改(自上次提交以来)。。将其推送到数据库。。然后命令那个trans。干杯很好的回答:)而且为了记录在案,EF实际上是在引擎盖下做的,当你提交更改()时。是的。在NH中,ISession实例实际上是UoW和iirc,它使用关联的事务来确定何时需要冲销-但我不能完全确定这一点,所以不要将其带到银行=)