C# 中的事务和 ExecuteNonQuery 错误

Posted

技术标签:

【中文标题】C# 中的事务和 ExecuteNonQuery 错误【英文标题】:Error in transation and ExecuteNonQuery in C# 【发布时间】:2013-10-25 12:40:17 【问题描述】:

我有以下错误:

当分配给命令的连接处于挂起的本地事务中时,ExecuteNonQuery 要求该命令具有事务。该命令的 Transaction 属性尚未初始化。

这个错误出现在函数executaComando

我的功能保存:

public void save(string[] arr)//, int lista)

    SqlConnection conexao = new SqlConnection(WebConfigurationManager.ConnectionStrings["strConexao"].ToString());
    conexao.Open();
    SqlTransaction trx = conexao.BeginTransaction();

    try
    
        //Truncate cliente_recurso
        BUProjetosDAL dal = new BUProjetosDAL();
        dal.excluirClientesRecurso(conexao);

        dtsRecursoClienteTableAdapters.RECURSO_CLIENTETabelaTableAdapter tabela = new dtsRecursoClienteTableAdapters.RECURSO_CLIENTETabelaTableAdapter();

        for (int j = 0; j <= 10; j++)  // <- here
            tabela.Insert(arr);
        

        trx.Commit();
    
    catch (SqlException ex)
    
        try
        
            trx.Rollback();
        
        catch (Exception exRollback)
        
            Response.Write(exRollback.Message);
          
    

函数 excluirClientesRecurso

public void excluirClientesRecurso(SqlConnection conexao)

    executaComando("TRUNCATE TABLE dbo.RECURSO_CLIENTE", conexao);

Function executaComando (----错误出现在这里----)

public void executaComando(string query, SqlConnection conexao)

    try
    
        SqlCommand cmd = new SqlCommand(query);
        cmd.Connection = conexao;
        cmd.ExecuteNonQuery();
        conexao.Close();
    
    catch (Exception ex)
    
        throw ex;
    

【问题讨论】:

顺便说一句,您可能想查看缺少 using 语句(这可能导致连接耗尽)以及您的 executaComando 中缺少参数化(这表明来自其他领域的代码可能使用输入的连接,这将是非常糟糕的 - 冒着 sql 注入的风险) 【参考方案1】:

嗯,正如错误所说的那样。您打开了一个事务,但没有将其分配给命令。

一个简单的解决方案是将其传递给executaComando

public void excluirClientesRecurso(SqlConnection conexao,
                                   SqlTransaction transaction)

    executaComando("TRUNCATE TABLE dbo.RECURSO_CLIENTE", conexao);


public void executaComando(string query, SqlConnection conexao,
                           SqlTransaction transaction)

    SqlCommand cmd = new SqlCommand(query);
    cmd.Connection = conexao;
    cmd.Transaction = transaction
    cmd.ExecuteNonQuery();
    conexao.Close();


// Usage
dal.excluirClientesRecurso(conexao, trx);

请注意,我删除了 executaComando 中的 try-catch,因为它没有起到任何作用。事实上,它做了坏事:它弄乱了异常的堆栈跟踪。

【讨论】:

【参考方案2】:

是的,确实如此。所以传入交易。这基本上是你说服它“我知道这里有交易”的方式。所以:

dal.excluirClientesRecurso(conexao, trx);
// ...
public void excluirClientesRecurso(SqlConnection conexao,
     SqlTransaction transaction = null)

    executaComando("TRUNCATE TABLE dbo.RECURSO_CLIENTE",
        conexao, transaction);


public void executaComando(string query, SqlConnection conexao,
     SqlTransaction trasaction = null)

    try
    
        SqlCommand cmd = new SqlCommand(query);
        cmd.Trasnaction = transaction;
        // ...

【讨论】:

【参考方案3】:

试试这个代码

    public bool updateusertable(string UserName,string Password,string Datetime)
            
                bool bResult = false;
               SqlTransaction tx;
                try
                
                    tx=Sqlconnect.Begintransaction;
                    SqlCommand Ocmd = new SqlCommand();
                   Sqlconnect= Cconnect.OpenSqlConnection();
                    Ocmd.Connection = Sqlconnect;
                    Ocmd.CommandType = CommandType.StoredProcedure;
                    Ocmd.CommandText = "SP_User_login_Update";
                    Ocmd.Parameters.Add("@UserName", SqlDbType.VarChar, 100).Value = UserName;
                    Ocmd.Parameters.Add("@Password", SqlDbType.VarChar, 100).Value = Password;
                    Ocmd.Parameters.Add("@lastlogin", SqlDbType.VarChar, 100).Value = Datetime;
                    int i = Ocmd.ExecuteNonQuery();
                    if (i <= 1)
                    
                        bResult = true;
                    else
                    
                        tx.Rollback();
                    
                
                catch (Exception ex)
                
                    string msg = ex.Message.ToString();
                    tx.Rollback();
                
                finally
                
                    tx.Commit();
                
                return bResult;
            

【讨论】:

以上是关于C# 中的事务和 ExecuteNonQuery 错误的主要内容,如果未能解决你的问题,请参考以下文章

C# 用command.ExecuteNonQuery() 执行update语句界面卡死,也不报错!??使用的是oracle数据库

C#:通过 ADO.NET 在 SQL Server 2008 上运行事务

C# sqlserver ExecuteNonQuery()方法详解

使用 ExecuteNonQuery c# 时出错

c# ExecuteNonQuery 总是返回零

错误 ExecuteNonQuery:连接属性尚未初始化 C# (Access)