我应该在以下代码的哪一行提交我的工作单元?

发布于 2024-08-26 05:33:09 字数 1465 浏览 13 评论 0原文

我在事务中有以下代码。我不确定我应该在哪里/何时提交我的工作单元。

我故意没有提到我正在使用什么类型的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不必你懂 2024-09-02 05:33:09

回答这个问题的一个很好的起点是企业架构模式中工作单元的定义(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 ):

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

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.

同尘 2024-09-02 05:33:09

对所有存储库进行所有操作后,在 #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.

只是在用心讲痛 2024-09-02 05:33:09

假设您的数据存储正在分配 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文