Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该在下面代码的哪一行提交我的工作单元?_C#_.net_Transactions_Unit Of Work - Fatal编程技术网

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

C# 我应该在下面代码的哪一行提交我的工作单元?,c#,.net,transactions,unit-of-work,C#,.net,Transactions,Unit Of Work,我有一个事务中的以下代码。我不确定我应该在哪里/什么时候提交我的工作单元 我特意没有提到我使用的是哪种类型的呼吸——例如Linq到Sql、实体框架4、NHibernate等等 如果有人知道在哪里,他们能解释一下为什么他们会说,在哪里?(我试图通过示例来理解模式,而不仅仅是让代码正常工作) 以下是我得到的:- using ( TransactionScope transactionScope = new TransactionScope (

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

我特意没有提到我使用的是哪种类型的呼吸——例如Linq到Sql、实体框架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();
}

对所有存储库执行所有操作后,在#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,它使用关联的事务来确定何时需要冲销-但我不能完全确定这一点,所以不要将其带到银行=)