I need help with realizing quite complex business logic which operates on many tables and executes quite a few SQL commands. However I want to be sure that the data will not be left in incosistent state and to this moment I don't see the solution which would not require nested transactions. I wrote a simple pseudo-code which illustrates a scenario similar to what I want to accomplish:
我需要帮助来实现非常复杂的业务逻辑,它可以在许多表上运行并执行相当多的SQL命令。但是我想确保数据不会处于不存在的状态,到目前为止我看不到不需要嵌套事务的解决方案。我写了一个简单的伪代码,它说明了一个类似于我想要完成的场景:
Dictionary<int, bool> opSucceeded = new Dictionary<int, bool> ();
for (int i = 0; i < 10; i++)
{
try
{
// this operation must be atomic
Operation(dbContext, i);
// commit (?)
opSucceeded[i] = true;
}
catch
{
// ignore
}
}
try
{
// this operation must know which Operation(i) has succeeded;
// it also must be atomic
FinalOperation(dbContext, opSucceeded);
// commit all
}
catch
{
// rollback FinalOperation and operation(i) where opSucceeded[i] == true
}
The biggest problem for me is: how to ensure that if the FinalOperation fails, all operations Operation(i) which succeeded are rolled back? Note that I also would like to be able to ignore failures of single Operation(i).
对我来说最大的问题是:如何确保如果FinalOperation失败,所有成功的操作(i)都会被回滚?请注意,我也希望能够忽略单个操作(i)的失败。
Is it possible to achieve this by using nested TransactionScope objects and if not - how would you approach such problem?
是否可以通过使用嵌套的TransactionScope对象来实现这一点,如果没有 - 你将如何处理这样的问题?
1 个解决方案
#1
2
If I am following your question, you want to have a series of operations against the database, and you capture enough information to determine if each operating succeeds or fails (the dictionary in your simplified code).
如果我正在关注您的问题,您希望对数据库进行一系列操作,并捕获足够的信息以确定每个操作是成功还是失败(简化代码中的字典)。
From there, you have a final operation that must roll back all of the successful operations from earlier if it fails itself.
从那里,你有一个最终的操作,如果它自己失败,必须从之前回滚所有成功的操作。
It would seem this is exactly the type of case that a simple transaction is for. There is no need to keep track of the success or failure of the child/early operations as long as failure of the final operation rolls the entire transaction back (here assuming that FinalOperation isn't using that information for other reasons).
看起来这正是简单交易的案例类型。只要最终操作的失败使整个事务回滚(这里假设FinalOperation没有因其他原因使用该信息),就不需要跟踪子/早期操作的成功或失败。
Simply start a transaction before you enter the block described, and commit or rollback the entire thing after you know the status of your FinalOperation. There is no need to nest the child operations as far as I can see from your current description.
只需在进入所描述的块之前启动事务,并在知道FinalOperation的状态后提交或回滚整个事务。从我当前的描述中可以看出,没有必要嵌套子操作。
Perhaps I a missing something? (Note, if you wanted to RETAIN the earlier/child operations, that would be something different entirely... but a failure of the final op rolling the whole package of operations back makes the simple transaction usable).
也许我错过了什么? (注意,如果你想保留早期/子操作,那将完全不同......但最终操作的失败使整个操作包回来使得简单的事务可用)。
#1
2
If I am following your question, you want to have a series of operations against the database, and you capture enough information to determine if each operating succeeds or fails (the dictionary in your simplified code).
如果我正在关注您的问题,您希望对数据库进行一系列操作,并捕获足够的信息以确定每个操作是成功还是失败(简化代码中的字典)。
From there, you have a final operation that must roll back all of the successful operations from earlier if it fails itself.
从那里,你有一个最终的操作,如果它自己失败,必须从之前回滚所有成功的操作。
It would seem this is exactly the type of case that a simple transaction is for. There is no need to keep track of the success or failure of the child/early operations as long as failure of the final operation rolls the entire transaction back (here assuming that FinalOperation isn't using that information for other reasons).
看起来这正是简单交易的案例类型。只要最终操作的失败使整个事务回滚(这里假设FinalOperation没有因其他原因使用该信息),就不需要跟踪子/早期操作的成功或失败。
Simply start a transaction before you enter the block described, and commit or rollback the entire thing after you know the status of your FinalOperation. There is no need to nest the child operations as far as I can see from your current description.
只需在进入所描述的块之前启动事务,并在知道FinalOperation的状态后提交或回滚整个事务。从我当前的描述中可以看出,没有必要嵌套子操作。
Perhaps I a missing something? (Note, if you wanted to RETAIN the earlier/child operations, that would be something different entirely... but a failure of the final op rolling the whole package of operations back makes the simple transaction usable).
也许我错过了什么? (注意,如果你想保留早期/子操作,那将完全不同......但最终操作的失败使整个操作包回来使得简单的事务可用)。