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