交易没有在c#中回滚

Sam*_*ami 4 c# sql-server transactions rollback

private void btnConfigure_Click(object sender, EventArgs e)
{
    try
    {
        dbConfigure dc = new dbConfigure();
        SqlTransaction tr = conn.BeginTransaction();
        cmd.Transaction = tr;
        if (dc.configuration(cmd, ps.tableNames))
            tr.Commit();
        else
        {
            tr.Rollback();
            mesg.show("Transaction is Rolled back");
        }
    }
    catch (Exception ex)
    {
        mesg.show(ex.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我在configuration方法中的任何地方遇到问题,那么它会返回false,我可以看到该消息Transaction is Rolled Back.但实际上事务并没有完全回滚,并且这个函数所做的数据库结构的一些变化仍然存在,尽管回滚是非常不希望的.我的问题是,交易回滚出现故障的可能性什么?

除了共享(上面)方法之外,我的项目中没有其他任何事务

小细节

我称configuration我的班级是一个非常冗长/复杂的功能dbConfigure.它对数据库结构进行了一些必要的更改.比如它

  1. 掉落foriegnKeys
  2. 删除主键
  3. 删除自动增加字段

    它在删除之前保存这些键并以所需的顺序/位置重新创建

conn是一个SqlConnection已经打开的,除此之外我没有任何连接

cmdconn.CreateCommand()我不使用任何地方比这其他命令

我从不关闭整个过程中的连接,但是SqlDataReader在configuration执行工作时会在功能上关闭.

Rem*_*anu 6

对数据库结构的更改不是事务性的,因此您无法回滚创建新表

BS.大多数DDL都是事务性的,可以回滚.只有涉及与非事务组件交互的更改(如文件系统,例如,向数据库添加新文件)才能回滚.如果在活动事务中调用,任何非事务性的DDL也将非常明确地引发异常.

添加和修改表非常明确是事务性的,并且可以通过示例轻松地进行说明:

begin transaction;
create table foo (a int);
select * from sys.tables where object_id = object_id('foo');
rollback;
select * from sys.tables where object_id = object_id('foo');
Run Code Online (Sandbox Code Playgroud)

因此问题在于OP丢失代码,未发布的部分.

作为一般注释,应尽可能使用System.Transactions(考虑到默认构造函数已损坏).如果使用SqlConnection.BeginTransaction,还是更好地依赖于IDisposable:

using (SqlTransaction trn = conn.BeginTransaction())
{
   ...
   trn.Commit ();
}
Run Code Online (Sandbox Code Playgroud)

System.Transactions应该受到青睐,因为它们不依赖于代码规则,事务范围中的任何代码SqlClient都会自动注册.

并且btw有错误的配置函数引发,不返回false.

并且在潜在的实际问题上:如何处理一个不可能在单个事务中注册的冗长,复杂的迁移(例如,它只能生成太多的日志).答案是唯一可行的选择是在迁移开始时进行数据库备份,如果迁移失败,则从此备份恢复.为每次迁移操作提供手动,经过测试和可靠的补偿操作以撤消迁移的替代方案非常困难,错误,并且最终不必要,因为从备份恢复非常简单且可证明是正确的.