我应该在以下代码的哪一行提交我的工作单元?
我在事务中有以下代码。我不确定我应该在哪里/何时提交我的工作单元。
我故意没有提到我正在使用什么类型的 Respoistory - 例如。 Linq-To-Sql、Entity Framework 4、NHibernate 等。
如果有人知道在哪里,请他们解释一下为什么他们说在哪里? (我试图通过示例来理解该模式,而不是仅仅让我的代码正常工作)。
这就是我所拥有的:-
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();
}
I have the following code which is in a transaction. I'm not sure where/when I should be commiting my unit of work.
On purpose, I've not mentioned what type of Respoistory i'm using - eg. Linq-To-Sql, Entity Framework 4, NHibernate, etc.
If someone knows where, can they please explain WHY they have said, where? (i'm trying to understand the pattern through example(s), as opposed to just getting my code to work).
Here's what i've got :-
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
回答这个问题的一个很好的起点是企业架构模式中工作单元的定义(http:// /martinfowler.com/eaaCatalog/unitOfWork.html ):
工作单元的边界是由业务事务的边界定义的 - 在这种情况下,它与数据库事务的边界同义(但在跨越多个请求的长时间运行的业务事务的情况下,这可能不是案件 )。
从上面的定义逆向工作,根据我对所示代码段的理解,您应该在业务事务结束时提交工作单元(#4)。
顺便说一句,您的数据库事务范围应始终小于 UoW 的范围(即 tx 范围位于对 UoW.Begin() 和 UoW.Commit() 的调用之间)。如果您的 UoW 跨越多个数据库事务,则当其中一个内部事务失败时,您将使用补偿事务来“重新平衡”UoW。在这种情况下,特别是如果您的 UoW 在 UoW.Begin() 和 UoW.Commit() 处创建自己的数据库事务边界,我将删除事务范围,因为这只会向代码添加不必要的噪音。
A good starting point for answering this question is the definition of Unit of Work from Patterns of Enterprise Architecture (http://martinfowler.com/eaaCatalog/unitOfWork.html ):
The boundaries of your unit of work are defined by the boundaries of your business transaction - in this case that is synonymous with the boundaries of the database transaction ( but in the case of a long running business transaction that spans multiple requests that may not be the case ).
Working backwards from the definition above and based on my understanding of the piece of code shown, you should commit the unit of work at the end of the business transaction (#4).
As an aside, your database transaction scopes should always be less than the scope of your UoW ( i.e. the tx scope resides between the call to UoW.Begin() and UoW.Commit() ). If your UoW spans multiple database transactions you would use a compensating transaction to "rebalance" the UoW if one of the inner transactions failed. In this instance, and especially if your UoW is creating it's own database transaction boundaries at UoW.Begin() and UoW.Commit() I would remove the transaction scope as this is simply adding unnecessary noise to the code.
对所有存储库进行所有操作后,在 #4 处提交。如果您提前提交,则不会提交该调用之后所做的更改。
Commit at #4 after all the operations to all the repositories are made. If you commit beforehand, the changes made after that call are not committed.
假设您的数据存储正在分配 ids,您必须提交 #1(使用 NHibernate,您甚至应该刷新),然后在最后提交 #4。
Assuming that your data store is assigning ids, you have to commit #1 (with NHibernate you should even flush), then at the end #4.