Error “There is already an open DataReader associated with this Command which must be closed first” when using 2 distinct commands

后端 未结 7 1712
春和景丽
春和景丽 2020-11-29 01:23

I have this legacy code :

 private void conecta()
 {  
     if (conexao.State == ConnectionState.Closed)
         conexao.Open();
 }

 public List

        
相关标签:
7条回答
  • 2020-11-29 01:43

    I suggest creating an additional connection for the second command, would solve it. Try to combine both queries in one query. Create a subquery for the count.

    while (dr3.Read())
    {
        dados_historico[4] = dr3["QT"].ToString(); //quantidade de emails lidos naquela verificação
    }
    

    Why override the same value again and again?

    if (dr3.Read())
    {
        dados_historico[4] = dr3["QT"].ToString(); //quantidade de emails lidos naquela verificação
    }
    

    Would be enough.

    0 讨论(0)
  • 2020-11-29 01:45

    I bet the problem is being shown in this line

    SqlDataReader dr3 = com2.ExecuteReader();
    

    I suggest that you execute the first reader and do a dr.Close(); and the iterate historicos, with another loop, performing the com2.ExecuteReader().

    public List<string[]> get_dados_historico_verificacao_email_WEB(string email)
        {
    
            List<string[]> historicos = new List<string[]>();
            conecta();
            sql = "SELECT * FROM historico_verificacao_email WHERE nm_email = '" + email + "' ORDER BY  dt_verificacao_email DESC, hr_verificacao_email DESC"; 
            com = new SqlCommand(sql, conexao);
            SqlDataReader dr = com.ExecuteReader();
    
            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    string[] dados_historico = new string[6];
                    dados_historico[0] = dr["nm_email"].ToString();
                    dados_historico[1] = dr["dt_verificacao_email"].ToString();
                    dados_historico[1] = dados_historico[1].Substring(0, 10);
                    //System.Windows.Forms.MessageBox.Show(dados_historico[1]);
                    dados_historico[2] = dr["hr_verificacao_email"].ToString();
                    dados_historico[3] = dr["ds_tipo_verificacao"].ToString();
                    dados_historico[5] = dr["cd_login_usuario"].ToString();
                    historicos.Add(dados_historico);
                }
    
                dr.Close();
    
                sql = "SELECT COUNT(e.cd_historico_verificacao_email) QT FROM emails_lidos e WHERE e.cd_historico_verificacao_email = '" + dr["cd_historico_verificacao_email"].ToString() + "'";
                tipo_sql = "seleção";
                com2 = new SqlCommand(sql, conexao);
    
                for(int i = 0 ; i < historicos.Count() ; i++)
                {
                    SqlDataReader dr3 = com2.ExecuteReader();
                    while (dr3.Read())
                    {
                        historicos[i][4] = dr3["QT"].ToString(); //quantidade de emails lidos naquela verificação
                    }
                    dr3.Close();
                }
    
            }
    
            return historicos;
    
    0 讨论(0)
  • 2020-11-29 01:46

    Try to combine the query, it will run much faster than executing an additional query per row. Ik don't like the string[] you're using, i would create a class for holding the information.

        public List<string[]> get_dados_historico_verificacao_email_WEB(string email)
        {
            List<string[]> historicos = new List<string[]>();
    
            using (SqlConnection conexao = new SqlConnection("ConnectionString"))
            {
                string sql =
                    @"SELECT    *, 
                                (   SELECT      COUNT(e.cd_historico_verificacao_email) 
                                    FROM        emails_lidos e 
                                    WHERE       e.cd_historico_verificacao_email = a.nm_email ) QT
                      FROM      historico_verificacao_email a
                      WHERE     nm_email = @email
                      ORDER BY  dt_verificacao_email DESC, 
                                hr_verificacao_email DESC";
    
                using (SqlCommand com = new SqlCommand(sql, conexao))
                {
                    com.Parameters.Add("email", SqlDbType.VarChar).Value = email;
    
                    SqlDataReader dr = com.ExecuteReader();
    
                    while (dr.Read())
                    {
                        string[] dados_historico = new string[6];
                        dados_historico[0] = dr["nm_email"].ToString();
                        dados_historico[1] = dr["dt_verificacao_email"].ToString();
                        dados_historico[1] = dados_historico[1].Substring(0, 10);
                        //System.Windows.Forms.MessageBox.Show(dados_historico[1]);
                        dados_historico[2] = dr["hr_verificacao_email"].ToString();
                        dados_historico[3] = dr["ds_tipo_verificacao"].ToString();
                        dados_historico[4] = dr["QT"].ToString();
                        dados_historico[5] = dr["cd_login_usuario"].ToString();
    
                        historicos.Add(dados_historico);
                    }
                }
            }
            return historicos;
        }
    

    Untested, but maybee gives some idea.

    0 讨论(0)
  • 2020-11-29 01:50

    Just add the following in your connection string:

    MultipleActiveResultSets=True;
    
    0 讨论(0)
  • 2020-11-29 01:59

    You can get such a problem when you are two different commands on same connection - especially calling the second command in a loop. That is calling the second command for each record returned from the first command. If there are some 10,000 records returned by the first command, this issue will be more likely.

    I used to avoid such a scenario by making it as a single command.. The first command returns all the required data and load it into a DataTable.

    Note: MARS may be a solution - but it can be risky and many people dislike it.

    Reference

    1. What does "A severe error occurred on the current command. The results, if any, should be discarded." SQL Azure error mean?
    2. Linq-To-Sql and MARS woes - A severe error occurred on the current command. The results, if any, should be discarded
    3. Complex GROUP BY on DataTable
    0 讨论(0)
  • 2020-11-29 02:01

    Add MultipleActiveResultSets=true to the provider part of your connection string. See the example below:

    <add name="DbContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
    
    0 讨论(0)
提交回复
热议问题