0

考虑

   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 数据库中对该实体进行任何更改。

如果没有事务范围,此代码将在几秒钟内执行,而在执行时使用则需要永远。我真正想要的是在 1,2 或 3 步骤中的任何一个出现异常的情况下仍然能够不更改基础记录。

显然,将 foreach 移到using中是不够的,因为如果至少有一次循环失败,那么好的记录也可能会被破坏,并且不会更新任何内容。

我需要了解更多关于交易机制的信息或可以在这里尝试哪些其他方法?

4

1 回答 1

2

TransactionScope是昂贵的,因为交易是昂贵的。

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

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


        scope.Complete();
    }
}

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

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

于 2013-07-18T12:04:26.580 回答