子父交易回滚

时间:2015-01-20 05:41:58

标签: c# transactionscope sqltransaction

我有一个场景,我必须处理多个.sQL文件,每个文件包含3-4个插入或更新查询,现在当文件中的任何查询失败时我做rollback整个事务处理意味着整个文件我们将被回滚,并且在该文件之前执行的所有其他文件将被提交,我想要一个选项,其中用户可以rollback整个事务意味着执行的文件中的所有查询以及在该特定文件包含错误之前执行的所有文件,如果用户想要跳过该特定文件并出现错误,我们将rollback包含错误的单个文件将提交所有其他文件,我现在正在使用SQL Transaction,没有TransactionScope但显然我可以如果需要也可以切换TransactionScope(), 目前我的代码伪(我想要的)如下

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()
}

2 个答案:

答案 0 :(得分:1)

您似乎正在寻找SavePoints,即部分回滚然后恢复更大的交易的选项。 AFAIK TransactionScope doesn't support 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)
)

答案 1 :(得分:0)

保留所有插入,更新try{..}catch(..){..}中的查询,如果发生任何异常,请在回滚中回滚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();
             }
         }
     }