1

我有一个场景,我必须处理多个.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()
}
4

2 回答 2

1

看来您正在寻找SavePoints,即部分回滚然后恢复更大事务的选项。AFAIKTransactionScope 不支持 SavePoints,因此您需要直接与本地提供者打交道(例如SqlClient,如果您的 RDBMS 是 Sql Server)。(即,您不能利用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)
)
于 2015-01-20T05:52:01.227 回答
0

将所有插入、更新查询保留在 a 中try{..}catch(..){..},如果发生任何异常,则在 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();
             }
         }
     }
于 2016-01-12T08:52:17.500 回答