在循环性能中创建新的事务范围

时间:2013-07-18 11:42:01

标签: .net sql-server-2008 transactions

考虑

   foreach (var myEntity in myEntities)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                // Some not very important code
                myEntity.ImageUrl = FixUrl(myEntity.ImageUrl);

                MyEntity additionalEntity = Clone(myEntity);
                additionalEntity.DateCreated = DateTime.Now;
                additionalEntity.CreatedBy = GetCurrentUser();

                //Step 1
                serverDbContext.Update(myEntity);
                //Step 2
                AddToQueue(myEntity);
                //Step 3
                anotherserverDbContext.Insert(myEntity);

                scope.Complete();
            }
        }

请注意,TransactionScope是在foreach语句中创建的。尝试使用此代码确认交易范围是昂贵的操作。

预计AddToQueue有时会抛出异常。在这种情况下,我们不希望在server1数据库中,也不希望在server2数据库中对该实体进行任何更改。

如果没有事务范围,此代码将在几秒钟内执行,而使用on执行则需要永久执行。 我真正想要的是在1,2或3步中的任何一个例外情况下仍然无法改变基础记录。

显然,使用移动内部的foreach是不够的,因为如果一个循环的至少一次传递失败,那么好的记录也可能会被破坏而且什么都不会更新。

我需要了解更多关于交易机制的信息,或者可以在这里尝试其他什么工具?

1 个答案:

答案 0 :(得分:1)

TransactionScope价格昂贵,因为交易费用很高。

如果您希望保证一致性,但又不想将整个操作作为一个工作单元,那么如果您将其并行化,则可能会发现操作完成得更快。实现这一目标的一种简单方法是使用Parallel.ForEach

myEntities.AsParallel().ForEach(entity =>
{
    using (TransactionScope scope = new TransactionScope())
    {
        // The operation to perform in parallel.


        scope.Complete();
    }
}

显然这引入了异步处理,因此您需要小心在并发运行的循环中共享的任何对象。

如果这不是一个选项,唯一的另一个实际选择是放弃原子一致性并转移到最终一致性系统。在这种情况下,它意味着在没有作用域的情况下运行,然后执行常规的“清理”操作来撤消任何不一致状态的“坏”记录。