C# 调用commit函数时,为什么SqlTransaction无法提交?
我遇到了这样一个问题:即使没有任何查询引发异常,所做的更改也会回滚。这很奇怪,因为代码在一个环境中工作,但没有在另一个环境中提交更改 下面是处理事务的函数。当我在提交上放置一个断点时,我点击了提交,我可以看到数据库中的更改,但是当事务被释放时,更改被回滚 更新:其他测试表明这不是事务的问题。如果事务完全从下面的代码中删除,则应用程序的行为方式相同。连接关闭时,更改将撤消C# 调用commit函数时,为什么SqlTransaction无法提交?,c#,sqltransaction,C#,Sqltransaction,我遇到了这样一个问题:即使没有任何查询引发异常,所做的更改也会回滚。这很奇怪,因为代码在一个环境中工作,但没有在另一个环境中提交更改 下面是处理事务的函数。当我在提交上放置一个断点时,我点击了提交,我可以看到数据库中的更改,但是当事务被释放时,更改被回滚 更新:其他测试表明这不是事务的问题。如果事务完全从下面的代码中删除,则应用程序的行为方式相同。连接关闭时,更改将撤消 publicbool事务(列出sqlStatements) { 使用(SqlConnection conn=newsqlcon
publicbool事务(列出sqlStatements)
{
使用(SqlConnection conn=newsqlconnection(connectionString))
{
conn.Open();
使用(SqlTransaction tran=conn.BeginTransaction())
{
尝试
{
foreach(sqlStatements中的字符串查询)
{
SqlCommand cmd=新的SqlCommand(查询、连接、传输);
cmd.CommandTimeout=300;
cmd.ExecuteNonQuery();
}
trans.Commit();
返回true;
}
捕获(SqlException sqlError)
{
事务回滚();
//日志异常
返回false;
}
}
}
}
虽然我很确定,但我还是在我这边试过了你的代码,它按预期工作。我再次重申,该方法对于事务处理来说已经足够好了。一旦事务被提交,就不能回滚
在上述方法中,事务处理与任何回滚无关。我想,你一直在错误的方向上调试。不过,您可以在这里粘贴原始方法,因为您可能正在执行其他一些数据库操作
突然,你提出了什么样的问题?请注意,DDL命令是自动提交的,事务将无效。当您说“可以看到数据库中的更改”时,您如何确定这一点?如果以下查询返回“已提交”的数据,我希望它们“在数据库中”(例如,在Sql Server Management Studio中跳过提交调用后运行此tsql):
如果数据确实提交了,我将运行SQL Server Profiler会话,查看是什么导致数据恢复。在这种情况下,似乎触发了一些单独的事件来恢复数据
如果数据未提交,则根据其他注释,您有某种事务计数不匹配。此问题最终可追溯到最近更新为包含事务的触发器
我们通过从触发器中删除事务解决了这个问题。为什么您知道没有例外。你总是抓住例外,什么也不做。。。只需回滚transactionCode对于事务单元来说看起来很好——尽管可以用更好的方式编写。您确定没有得到任何异常,因为您在catch块中吞下了异常。通过执行上述方法,您得到的是真返回值还是假返回值?您应该在catch块内设置一个断点,查看它是否被命中,然后在catch返回假返回之前检查异常。事务一旦提交,就永远不会回滚。这在技术上是不可能的。删除异常处理代码。不要手动回滚。删除基于bool返回的错误报告。@从头开始我确信我没有收到异常。我能够在调试模式下单步执行代码时触发相同的行为。查询都是insert/update/delete语句。我的结论是,其他地方可能存在问题,可能是数据库设置。如果您具有完全恢复模式,您仍然可以回滚到事务运行前的某个时刻。但是,回滚中可能还涉及其他事务。
public bool Transaction(List<string> sqlStatements)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlTransaction tran = conn.BeginTransaction())
{
try
{
foreach (string query in sqlStatements)
{
SqlCommand cmd = new SqlCommand(query, conn, tran);
cmd.CommandTimeout = 300;
cmd.ExecuteNonQuery();
}
tran.Commit();
return true;
}
catch (SqlException sqlError)
{
tran.Rollback();
//Log Exception
return false;
}
}
}
}
-- Force the isolation level to "read committed" so we
-- guarantee we are getting data that has definitely been committed.
-- If the data changes back, it must have been from a separate operation.
set transaction isolation level read committed
begin tran
select * from MyTableWithExpectedChanges;
-- You aren't changing anything so this can be rollback or commit
rollback tran