2 개의 고유 한 명령을 사용할 때 "이 명령과 관련된 열린 DataReader가 이미 있으며 먼저 닫아야합니다."오류
이 레거시 코드가 있습니다.
private void conecta()
{
if (conexao.State == ConnectionState.Closed)
conexao.Open();
}
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);
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;
- 최적의 솔루션은 한 번에 두 명의 독자를 열 필요가없는 형태로 솔루션 을 변환 하는 것입니다. 이상적으로는 단일 쿼리 일 수 있습니다. 지금 할 시간이 없습니다.
문제가 너무 특별해서 동시에 더 많은 리더를 열어야하고 요구 사항이 SQL Server 2005 DB 백엔드 이전 버전을 허용하지 않는 경우 마법 단어는 MARS (Multiple Active Result Sets) 입니다. 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
해결책이 될 수 있지만 위험 할 수 있으며 많은 사람들이 싫어합니다.
참고
- "현재 명령에 심각한 오류가 발생했습니다. 결과가있는 경우 삭제해야합니다." SQL Azure 오류는 무엇입니까?
- Linq-To-Sql 및 MARS 문제-현재 명령에서 심각한 오류가 발생했습니다. 결과 (있는 경우)를 삭제해야합니다.
- DataTable의 복잡한 GROUP BY
이 줄에 문제가 표시되고 있다고 확신합니다.
SqlDataReader dr3 = com2.ExecuteReader();
첫 번째 판독기를 실행하고 a dr.Close();
및 반복을 historicos
수행하고 다른 루프를 사용하여 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;
쿼리를 결합하면 행당 추가 쿼리를 실행하는 것보다 훨씬 빠르게 실행됩니다. 당신이 사용하고있는 string []이 마음에 들지 않습니다. 정보를 담기위한 클래스를 만들겠습니다.
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;
}
테스트되지 않았지만 maybee가 몇 가지 아이디어를 제공합니다.
MultipleActiveResultSets=true
연결 문자열의 공급자 부분에 추가 합니다. 아래 예를 참조하십시오.
<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" />
'Program Tip' 카테고리의 다른 글
Zipalign-명령을 찾을 수 없음-MAC 터미널 (0) | 2020.11.12 |
---|---|
Laravel의 블레이드 템플릿을 사용하여 레이아웃에 변수를 어떻게 전달합니까? (0) | 2020.11.12 |
RabbitMQ 3.3.1은 게스트 / 게스트로 로그인 할 수 없습니다. (0) | 2020.11.12 |
Android Studio에서 제목 표시 줄을 제거하려면 어떻게합니까? (0) | 2020.11.12 |
OwinStartupAttribute 오류가 포함 된 어셈블리를 찾을 수 없습니다. (0) | 2020.11.12 |