C# 事务不在c中回滚#
如果我在C# 事务不在c中回滚#,c#,sql-server,transactions,rollback,C#,Sql Server,Transactions,Rollback,如果我在configuration方法中的任何地方遇到问题,那么它将返回false,并且我可以看到消息事务已回滚。但实际上,事务并没有完全回滚,并且该函数对数据库结构所做的一些更改仍然存在,尽管回滚是非常不希望的。我的问题是事务回滚出现故障的可能性是什么? 在我的项目中,除了共享(上述)方法外,我没有其他任何事务 小细节 我正在调用类dbConfigure的一个非常长/复杂的函数configuration。它对数据库结构进行了一些必要的更改。e、 g.它 丢钥匙 删除主键 删除自动递增字段 它在
configuration
方法中的任何地方遇到问题,那么它将返回false,并且我可以看到消息事务已回滚
。但实际上,事务并没有完全回滚,并且该函数对数据库结构所做的一些更改仍然存在,尽管回滚是非常不希望的。我的问题是事务回滚出现故障的可能性是什么?
在我的项目中,除了共享(上述)方法外,我没有其他任何事务
小细节
我正在调用类dbConfigure
的一个非常长/复杂的函数configuration
。它对数据库结构进行了一些必要的更改。e、 g.它
conn
是一个已经打开的SqlConnection
,除此之外,我在任何地方都不使用连接
cmd
是conn.CreateCommand()
除此之外,我在任何地方都不使用命令
在整个过程中,我从未关闭连接,但是SqlDataReader在执行其工作时会在
配置中关闭。这可以通过使用TransactionScope而不是在代码中创建SqlTransaction来实现吗。大概是这样的:
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);
}
}
例如,对数据库结构的更改不是事务性的,所以不能回滚新表的创建
学士学位。大多数DDL是事务性的,可以回滚。只有涉及与非事务组件交互的更改(如文件系统,例如向数据库添加新文件)才能回滚。如果在活动事务中调用,任何非事务性DDL也会非常明确地引发异常
添加和修改表是非常显式的事务性操作,可以很容易地用一个示例加以说明:
using (TransactionScope transaction = new TransactionScope())
{
...perform your database action here
scope.Complete()
}
因此,问题在于OP缺少代码,部件未发布
作为一般性意见,应尽可能使用System.Transactions(考虑到这一点)。如果使用SqlConnection.BeginTransaction,则最好依赖IDisposable:
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');
虽然事务不依赖于代码规则,但事务范围内的任何代码SqlClient都将自动注册
顺便说一句,配置函数在出错时引发,而不是返回false
还有一个潜在的实际问题:如何处理一个长而复杂的迁移,而这个迁移不可能在一个事务中注册(例如,它只会生成太多的日志)。答案是,唯一可行的选择是在迁移开始时进行数据库备份,如果迁移失败,则从该备份进行恢复。为每个迁移操作提供手动、经过测试且可靠的补偿操作以撤消迁移的替代方法非常困难、容易出错,而且最终是不必要的,因为从备份恢复要简单得多,而且可以证明是正确的 非常感谢@Morten Jacobsen。我不这么想。所以我得到了答案。但是,如果有什么方法可以做到这一点,请你也给我指点一下好吗?如果另一个创建表失败,是否意味着回滚创建表?是@GeorgeStocker。虽然你说的链接似乎对解决我的问题没有多大帮助。然而,我很高兴通过这个问题我学到了一些东西。最好的答案可能是帮助我找到一种方法来回滚数据库中的结构更改。但至少你的评论提供了一些指导和动力。你可以把它作为答案贴出来,如果我找不到更好的答案,我肯定会接受的。因为这是有效的回答,所以我删除了我之前的评论,因为正如Remus Rusanu指出的,在SQL Server中进行事务性DDL实际上是可能的。我的评论是基于Oracle数据库的,这是不可能的。可能是,但我认为不是。因为我被告知,结构上的更改是无法回滚的。可能有一些方法你是对的,这在SQL server中是可能的(我不知道)。。然而,您可能应该指出,据我所知,其特定于供应商的Oracle不允许这样做。由于OP没有指定要连接到哪个数据库,因此这种方法可能不可行。@MortenJacobsen:问题被标记为“sql server”,OP代码使用SqlClient组件。至于DDL transact-Capability,答案要复杂得多:但最终没有必要陷入困境,因为这个问题显然是针对某个特定供应商的。我明白了,我没有注意到标签。回答得好。我需要一些时间:)
using (SqlTransaction trn = conn.BeginTransaction())
{
...
trn.Commit ();
}