【问题标题】:Commit multiple SqlCommands with SqlTransaction使用 SqlTransaction 提交多个 SqlCommand
【发布时间】:2015-06-18 01:56:04
【问题描述】:

我正在尝试将SqlCommand 的列表传递给持有与数据库的连接的成员函数。

public void CommitAsTransaction(List<SqlCommand> commands) {
    SqlTransaction transaction = null;
    SqlConnection connection = null;

    try {
        connection = this.CreateSqlConnection();
        connection.Open();

        transaction = connection.BeginTransaction("TransactionID");

        foreach (SqlCommand cmd in commands) {
            cmd.Transaction = transaction;
            cmd.Connection = connection;
            cmd.ExecuteNonQuery();
        }

        transaction.Commit();
    }
    catch (Exception ex) {
        transaction.Rollback();
    }

    connection.Close();
}

这是我目前拥有的。发生错误是因为该命令似乎正在原地执行,并且从未到达 transaction.Commit();。我见过很多人这样做,但不确定我做错了什么。

PS:问题在于将要执行的存储过程必须全部在单个事务中运行,我无法控制它们并且它们是加密的,它们必须在事务中运行的原因是因为它们创建有 PK 要求的表中的临时记录。

【问题讨论】:

  • 您说永远不会达到提交。会发生什么?
  • 另外,我相信我会将连接和事务放入使用块中。
  • 我得到一个 SQL 异常,指出它们是临时表上的主键约束,这意味着 SqlCommand 实际在服务器上执行。
  • 您的 SQL 实例上配置了什么隔离级别?
  • 事务并不意味着命令在提交之前不会执行 - 它们意味着命令会立即执行,但它们的 影响 不会在事务直到提交。

标签: c# sql-server sqlcommand sqltransaction


【解决方案1】:

你能改用事务范围吗? 比如:

// place this code inside CommitAsTransaction

using (TransactionScope scope = new TransactionScope())
{
     Boolean AllOK = true;
     SqlConnection connection = this.CreateSQLConnection();
     try
     {
         connection.Open()
     }
     catch (Exception e)
     {
       // deal with it how you need to
       AllOK = false;
     }

     if (AllOK)
     {
        foreach(SQlCommand cmd in Commands)
        {
            try
            {
                 cmd.Connection = connection;
                 cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
               // Deal with it.. 
               AllOK = false;
               break;
            }
        }

        if (AllOK)
        {
           scope.Complete();
           try
           {
               connection.Close();
           }
           catch (Exception e)
           {
             // deal with it
           }
        }
    }
}

【讨论】:

    【解决方案2】:

    非常感谢。我最终根据其他人的综合答案自己弄清楚了,谢谢,这是我使用的代码:

    public List<Models.eConnectModels.eConnStatus> CommitAsTransaction(List<SqlCommand> commands) 
    {
        SqlTransaction transaction = null;
        SqlConnection connection = null;
        List<eConnStatus> ErrorList = new List<eConnStatus>();
                
        try 
        {
            connection = this.CreateSqlConnection();
            connection.Open();
                    
            transaction = connection.BeginTransaction(IsolationLevel.ReadUncommitted, "TransactionID");
    
            foreach (SqlCommand cmd in commands) 
            {
                eConnStatus curErr = new eConnStatus();
                cmd.Transaction = transaction;
                cmd.Connection = connection;
                
                SqlParameter errorString = cmd.Parameters.Add("@oErrString", SqlDbType.VarChar);
                errorString.Direction = ParameterDirection.Output;
                errorString.Size = 8000;
    
                SqlParameter errorStatus = cmd.Parameters.Add("@O_iErrorState", SqlDbType.Int);
                errorStatus.Direction = ParameterDirection.Output;
    
                cmd.ExecuteNonQuery();
                curErr.ErrorState = (int)cmd.Parameters["@O_iErrorState"].Value;
                curErr.ErrorMessage = (string)cmd.Parameters["@oErrString"].Value;
                ErrorList.Add(curErr);
            }
    
            transaction.Commit();
        }
        catch (Exception ex) 
        {
            transaction.Rollback();
            connection.Close();
            throw ex;
        }
        
        connection.Close();
        return ErrorList;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-29
      • 1970-01-01
      • 2013-12-13
      • 2012-01-23
      • 2010-10-11
      • 2021-03-12
      相关资源
      最近更新 更多