【问题标题】:c# ExecuteReader requires the command to have a transaction when the connection assigned to the command is in a pending local transactionc# ExecuteReader 要求命令有一个事务,当分配给命令的连接处于挂起的本地事务中时
【发布时间】:2018-07-05 14:11:07
【问题描述】:

我遇到了相同的错误,我看到多个线程有,在谷歌搜索 2 天后,我似乎无法解决这个问题,我不明白为什么。我简化了一些与 sqltransaction 部分无关的代码。

    conn.Open();

using (SqlTransaction sqlTran = conn.BeginTransaction())
{
    SqlCommand command = new SqlCommand("", conn, sqlTran);
    log.Info("Connection Opened");


    foreach (var eventData in reqData)
    {
        ProcessMessage(eventData, req, conn, log, sqlTran, command);
    }

    sqlTran.Commit();
    sqlTran.Dispose();
}
conn.Close();

public static void ProcessMessage(JObject messageData, HttpRequestMessage req, SqlConnection conn, TraceWriter log, SqlTransaction sqlTran, SqlCommand command)
{
        //query building stuff
        PerformTransaction(req, query, conn, log, sqlTran, command);
}

public static void PerformTransaction(HttpRequestMessage req, string query, SqlConnection conn, TraceWriter log, SqlTransaction sqlTran, SqlCommand command)
{
     try
        {
            command.ExecuteNonQuery();
            log.Info("Query Executed Successfully");
        }
     catch
        {
            log.Info("Transaction Execution Error");
            sqlTran.Rollback();
            throw;
        }
}

【问题讨论】:

  • 鉴于您的错误消息提到了ExecuteReader,我倾向于认为问题不在此代码块中,因为没有调用ExecuteReader。也许您在同一事务中的其他地方调用它,但忘记在命令对象上设置 sqlTran?
  • 就是这样,我无法将评论标记为答案,但我们的谈话确实帮助我更好地组织了我的代码。
  • 我很高兴能提供帮助。对于信息,您的原始语句集非常适合一个事务中的多个插入。我对插入、删除和更新使用了类似的方法

标签: c# sql-server


【解决方案1】:

您忘记在您的PerformTransaction() 中添加command.Transaction = sqlTran; 之前的command.ExecuteNonQuery();

public static void PerformTransaction(HttpRequestMessage req, string query, SqlConnection conn, TraceWriter log, SqlTransaction sqlTran, SqlCommand command)
{
     try
        {
            command.Transaction = sqlTran;
            command.ExecuteNonQuery();
            log.Info("Query Executed Successfully");
        }
     catch
        {
            log.Info("Transaction Execution Error");
            sqlTran.Rollback();
            throw;
        }
}

编辑: 实际上,您的问题是当sqlTran 所做的第一个事务尚未完成时,您正试图对多个事务使用相同的sqlTran。换句话说,您在调用command.ExecuteNonQuery()之前已经启动了另一个未提交的事务

尝试将sqlTran.Commit() 移动到try 块内,位于Command.ExecuteNonQuery() 之后的PerformTransaction() 中。这样,在您尝试执行另一个事务之前,当前事务就会被提交。

public static void PerformTransaction(HttpRequestMessage req, string query, SqlConnection conn, TraceWriter log, SqlTransaction sqlTran, SqlCommand command)
{
     try
        {
            command.ExecuteNonQuery();
            log.Info("Query Executed Successfully");
            sqlTran.Commit();
            log.Info("Transaction Commited Successfully");
        }
     catch
        {
            log.Info("Transaction Execution Error");
            sqlTran.Rollback();
            throw;
        }
}

【讨论】:

  • 他不是在命令的构造函数中指定了事务吗?
  • @Cato 刚刚注意到。
  • 传输和连接是否正确连接?可以只传递 tran 并从 tran.connection 属性获取连接。嵌套事务是可能的吗? (抱歉没用过)
  • 我的目标是拥有多个交易,如果其中任何一个未能将它们全部回滚,这不可能吗?
  • @user1552172 是的,只需创建多个事务并将它们全部调用。而不是使用相同的事务。如果它们都成功运行,那么您可以将它们全部提交。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多