子父交易回滚
我有一个场景,我必须处理多个.sQL
文件,每个文件包含3-4个插入或更新查询,现在当文件中的任何查询失败时,我rollback
整个事务意味着我们将回滚整个文件,以及所有其他在该文件被提交之前执行的文件,我想要一个选项,其中用户可以rollback
整个事务意味着执行的文件中的所有查询以及在该特定文件包含错误之前执行的所有文件,并且如果用户想要跳过该特定文件但是我们将只是rollback
包含错误的单个文件所有其他文件将被提交,我现在正在使用SQL Transaction,没有TransactionScope
但显然我可以切换到TransactionScope()
如果需要和可能,目前我的代码伪(我想要的)是as如下
Var Files[] for each (string query in Files) { Execute(Query) IF(TRUE) CommitQuery() Else result=MBOX("IF You want to abort all files or skip this one") if(result=abort) rollbackall() else QueryRollBack() }
看来你正在寻找SavePoints ,即部分回滚然后恢复更大的交易的选项。 AFAIK TransactionScope
不支持SavePoints,因此您需要直接处理本机提供程序(例如,如果您的RDBMS是Sql Server,则为SqlClient
)。 (即,您无法利用TransactionScope
实现DTC
等效的SavePoints
,例如跨分布式数据库,不同的RDBMS或并行事务)
也就是说,我会建议一种策略,用户在事务处理开始之前选择跳过或中止,因为等待UI响应的代价很高,而大量行仍然被锁定 – 这可能会导致争用问题。
编辑
这是使用SavePoints
的一小部分示例。 插入Foo1和Foo3,Foo2回滚到前一个保存点。
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Foo"].ConnectionString)) { conn.Open(); using (var txn = conn.BeginTransaction("Outer")) { txn.Save("BeforeFoo1"); InsertFoo(txn, "Foo1"); txn.Save("BeforeFoo2"); InsertFoo(txn, "Foo2"); txn.Rollback("BeforeFoo2"); txn.Save("BeforeFoo3"); InsertFoo(txn, "Foo3"); txn.Commit(); } }
InsertFoo
在哪里:
private void InsertFoo(SqlTransaction txn, string fooName) { using (var cmd = txn.Connection.CreateCommand()) { cmd.Transaction = txn; cmd.CommandType = CommandType.Text; cmd.CommandText = "INSERT INTO FOO(Name) VALUES(@Name)"; cmd.Parameters.Add(new SqlParameter("@Name", SqlDbType.VarChar)).Value = fooName; cmd.ExecuteNonQuery(); } }
而基础表是:
create table Foo ( FooId INT IDENTITY(1,1) NOT NULL PRIMARY KEY, Name NVARCHAR(50) )
保持所有insert,更新try{..}catch(..){..}
,如果发生任何exception,请在catch roll中返回db事务。
private void InsertFoo(SqlTransaction txn, string fooName) { using (var cmd = txn.Connection.CreateCommand()) { try { do your process here... cmd.Commit(); } catch(Exception ex) { cmd.Rollback(); } } }