Ошибка «Существует уже открытый DataReader, связанный с этой Командой, который должен быть закрыт первым» при использовании 2 отдельных команд

У меня есть этот код устаревшего кода:

private void conecta() { if (conexao.State == ConnectionState.Closed) conexao.Open(); } public List get_dados_historico_verificacao_email_WEB(string email) { List historicos = new List(); 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); dados_historico[2] = dr["hr_verificacao_email"].ToString(); dados_historico[3] = dr["ds_tipo_verificacao"].ToString(); 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"; conecta(); com2 = new SqlCommand(sql, conexao); SqlDataReader dr3 = com2.ExecuteReader(); while (dr3.Read()) { //quantidade de emails lidos naquela verificação dados_historico[4] = dr3["QT"].ToString(); } dr3.Close(); conexao.Close(); //login dados_historico[5] = dr["cd_login_usuario"].ToString(); historicos.Add(dados_historico); } dr.Close(); } else { dr.Close(); } conexao.Close(); return historicos; } 

Я создал две команды разделения для исправления проблемы, но она по-прежнему продолжается: «Существует уже открытый DataReader, связанный с этой Командой, который должен быть закрыт первым».

Дополнительная информация: тот же код работает в другом приложении.

Я предлагаю создать дополнительное соединение для второй команды, решит ее. Попробуйте объединить оба запроса в одном запросе. Создайте подзапрос для подсчета.

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

Почему переопределить одно и то же значение снова и снова?

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

Было бы достаточно.

Просто добавьте в строку подключения следующее:

 MultipleActiveResultSets=True; 
  1. Оптимальным решением может быть попытка превратить ваше решение в форму, где вам не нужно открывать сразу два считывателя. В идеале это может быть один запрос. У меня нет времени на это.
  2. Если ваша проблема настолько особенная, что вам действительно нужно, чтобы одновременно открывалось больше читателей, а ваши требования позволяют не раньше, чем бэкэнд базы данных SQL Server 2005, то волшебным словом является MARS (несколько активных наборов результатов) . http://msdn.microsoft.com/en-us/library/ms345109%28v=SQL.90%29.aspx . Решение связанного раздела Bob Vale показывает, как включить его: укажите в строке соединения MultipleActiveResultSets=true . Я просто говорю это как интересную возможность, но вы должны скорее преобразовать свое решение.

    • чтобы избежать упомянутой возможности SQL-инъекции, установите параметры самому SQLCommand, а не внедряйте их в строку запроса. Строка запроса должна содержать только ссылки на параметры, которые вы передаете в SqlCommand.

Вы можете получить такую ​​проблему, когда у вас two different commands в одном соединении – особенно вызов второй команды в loop . Это вызывает вторую команду для каждой записи, возвращенной из первой команды. Если есть 10 000 записей, возвращенных первой командой, эта проблема будет более вероятной.

Я использовал, чтобы избежать такого сценария, сделав его как одну команду. Первая команда возвращает все необходимые данные и загружает их в DataTable.

Примечание: MARS может быть решением, но это может быть рискованным, и многим людям это не нравится.

Справка

  1. Что означает «Суровая ошибка в текущей команде. Результаты, если они есть, должны быть отброшены». Ошибка SQL Azure?
  2. Проблемы с Linq-To-Sql и MARS. В текущей команде возникла серьезная ошибка. Результаты, если таковые имеются, должны быть отброшены
  3. Комплекс GROUP BY по DataTable

Уверен, что проблема показана в этой строке

 SqlDataReader dr3 = com2.ExecuteReader(); 

Я предлагаю вам выполнить первый читатель и сделать dr.Close(); и итерации historicos , с другим циклом, выполняющим com2.ExecuteReader() .

 public List get_dados_historico_verificacao_email_WEB(string email) { List historicos = new List(); 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; 

Попробуйте объединить запрос, он будет работать намного быстрее, чем выполнение дополнительного запроса для каждой строки. Ik не нравится строка [], которую вы используете, я бы создал class для хранения информации.

  public List get_dados_historico_verificacao_email_WEB(string email) { List historicos = new List(); 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; } 

Непроверенный, но maybee дает некоторую идею.

Добавьте MultipleActiveResultSets=true для части поставщика вашей строки подключения. См. Пример ниже:

  
  • Прикрепите файл из MemoryStream к MailMessage в C #
  • Проверка, является ли двойной (или плавающий) NaN в C ++
  • Связывание параметров OracleCommand SQL
  • «C» sizeof с типом или переменной
  • Шаблонный набор - вызов функции для каждого элемента
  • Почему учебник EF 6 использует асинхронные вызовы?
  • visual c ++: # включить файлы из других проектов в одном решении
  • Когда удалять CancellationTokenSource?
  • Почему внешняя ссылка не связана со статической переменной?
  • Как добавить / обновить дочерние сущности при обновлении родительского объекта в EF
  • Интерфейсы C # - В чем смысл?
  • Interesting Posts
    Давайте будем гением компьютера.