我使用这样的环境事务:
using(TransactionScope tran = new TransactionScope()) {
CallAMethod1();//INSERT
CallAMethod2();//INSERT
tran.Complete();
}
CallAMethod2();
方法返回受影响的行 =-264
因此它无法插入,但是第一个插入已提交!
我想知道如何使用 ambient transaction
以及如果第二种方法有多个需要内部事务的操作,我应该将这些操作放在内部事务中吗?
像这样:
DAL_Helper.Begin_Transaction();
//------Fill newKeysDictioanry
affectedRow = DBUtilities.InsertEntityWithTrans("table2", newKeysDictioanry, DAL_Helper);
if (affectedRow == 1)
{
if (!string.IsNullOrEmpty(sp_confirm))
{
result_dt = UserTransactionDAL.Run_PostConfirm_SP(sp_PostConfirm, OBJ.ValuesKey, DAL_Helper);
if (result_dt.Rows.Count > 0 && result_dt.Rows[0][0].ToString() == "0")
{
DAL_Helper.current_trans.Commit();
if (DAL_Helper.connectionState == ConnectionState.Open)
{
DAL_Helper.Close_Connection();
}
return 1;// affectedRow;
}
else
{
DAL_Helper.current_trans.Rollback();
if (DAL_Helper.connectionState == ConnectionState.Open)
{
DAL_Helper.Close_Connection();
}
return -2;
}
}
//etc
最佳答案
1) 您需要检查 tran.Complete();
是否被调用。如果 tran.Complete();
被调用,TransactionScope 被认为成功完成。
来自 MSDN
When your application completes all work it wants to perform in a transaction, you should call the Complete method only once to inform that transaction manager that it is acceptable to commit the transaction. Failing to call this method aborts the transaction.
调用tran.Complete();
是为了通知交易管理器完成交易。实际上,事务管理器不会跟踪您的 Db 适配器,也不知道连接中的操作是成功还是失败。您的应用程序必须通过调用 Complete 告知它
How does TransactionScope roll back transactions?
要使您的交易失败,只需确保您没有在代码中调用 tran.Complete();
:
If no exception occurs within the transaction scope (that is, between the initialization of the TransactionScope object and the calling of its Dispose method), then the transaction in which the scope participates is allowed to proceed. If an exception does occur within the transaction scope, the transaction in which it participates will be rolled back.
在您的情况下,如果您认为操作失败,您可以在 CallAMethod2();
中抛出异常,因此 tran.Complete();
是 < strong>不调用,事务被回滚。
2) 您可以检查的第二件事是您的连接是否在事务中登记。如果未登记连接,TransactionScope 不会回滚。可能出现的问题是:
- 如果连接在进入事务范围之前就存在,则不会登记:Does TransactionScope work with pre-existing connections?
- 您的基础连接不支持自动登记。
在这些情况下,您可以尝试手动注册您的连接(从上面的链接中提取):
connection.EnlistTransaction(Transaction.Current)
关于你的第二个问题:
what if the second method has more than one action which need internal transaction , should i put these actions in internal transaction ?
我想说这实际上取决于您是否将 CallAMethod2();
视为自动 操作,这意味着您可以在别处直接调用它而无需将其包装在事务中.大多数情况下,创建内部事务是有意义的,因为事务可以嵌套。对于您的情况,建议在您的 CallAMethod2();
中也使用 TransactionScope,我们在创建新事务范围时有一些选项:
The TransactionScope class provides several overloaded constructors that accept an enumeration of the type TransactionScopeOption, which defines the transactional behavior of the scope. A TransactionScope object has three options:
Join the ambient transaction, or create a new one if one does not exist.
Be a new root scope, that is, start a new transaction and have that transaction be the new ambient transaction inside its own scope.
Not take part in a transaction at all. There is no ambient transaction as a result.
选择哪一个取决于您的应用。就您而言,我想您可以选择第一个选项。以下是来自 MSDN 的示例
void RootMethod()
{
using(TransactionScope scope = new TransactionScope())
{
/* Perform transactional work here */
SomeMethod();
scope.Complete();
}
}
void SomeMethod()
{
using(TransactionScope scope = new TransactionScope())
{
/* Perform transactional work here */
scope.Complete();
}
}
关于c# - 环境事务中的 TransactionScope 错误不会回滚事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28191333/