Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

DaniloTec

[Resolvido] SqlDateReader dentro de um RowDataBound

Recommended Posts

Boa tarde gente.

Estou executando um SqlDataReader dentro de um RowDataBound e está exibindo o seguinte erro:

There is already an open DataReader associated with this Command which must be closed first.

Será que é porque ele executa o SqlDataReader em cada linha?

if (e.Row.RowType == DataControlRowType.DataRow){
   string strDepartamento = "";
   SqlCommand sqlDepartamentos = new SqlCommand("select txt_departamento from tbl_departamentos where id_departamentos in (" + e.Row.Cells[4].Text + ")", conn);
   SqlDataReader drDepartamentos = sqlDepartamentos.ExecuteReader();
   while(drDepartamentos.Read()){
	  strDepartamento += drDepartamentos["txt_departamento"].ToString();
   }
   drDepartamentos.Close();
   drDepartamentos.Dispose();
   sqlDepartamentos.Dispose();
}
Mas como vcs podem ver, eu estou fechando o dr.

Existe outra forma de executer uma query dentro do RowDataBound?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então, Quintelab. Eu já tinha tentado isso e tmb não deu certo. Ele alega que já existe uma conexão aberta.

protected void gvCandidatos_RowDataBound(object sender, GridViewRowEventArgs e)
	{
		if (e.Row.RowType == DataControlRowType.DataRow)
		{
			string strDepartamento = "";
			conn.Open();
			SqlCommand sqlDepartamentos = new SqlCommand("select txt_departamento from tbl_departamentos where id_departamentos in (" + e.Row.Cells[4].Text + ")", conn);
			SqlDataReader drDepartamentos = sqlDepartamentos.ExecuteReader();
			while(drDepartamentos.Read()){
				strDepartamento += drDepartamentos["txt_departamento"].ToString();
			}
			drDepartamentos.Close();
			drDepartamentos.Dispose();
			sqlDepartamentos.Dispose();
			conn.Close();
		}
	}

The connection was not closed. The connection's current state is open.

Mas como você pode ver, não há nenhuma conexão aberta.

Outra coisa, pq essas páginas da msdn não tem barra de rolagem? rs

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que descobri porque ele exibe o erro, só não sei o que fazer para resolver.

Tenho o seguinte codigo que popula o grid:

try {
   conn.Open();
   SqlCommand sqlBusca = new SqlCommand(strBusca, conn);
   SqlDataReader drBusca = sqlBusca.ExecuteReader();
   gvCandidatos.DataSource = drBusca;
   gvCandidatos.DataBind();
   drBusca.Close();
   drBusca.Dispose();
   sqlBusca.Dispose();
   conn.Close();
}catch(System.Data.SqlClient.SqlException ex){
   Response.Write(ex.Message);
}
E o código dentro do RowData:

protected void gvCandidatos_RowDataBound(object sender, GridViewRowEventArgs e)
	{
		if (e.Row.RowType == DataControlRowType.DataRow)
		{
			string strDepartamento = "";
			conn.Open();
			SqlCommand sqlDepartamentos = new SqlCommand("select txt_departamento from tbl_departamentos where id_departamentos in (" + e.Row.Cells[4].Text + ")", conn);
			SqlDataReader drDepartamentos = sqlDepartamentos.ExecuteReader();
			while(drDepartamentos.Read()){
				strDepartamento += drDepartamentos["txt_departamento"].ToString();
			}
			drDepartamentos.Close();
			drDepartamentos.Dispose();
			sqlDepartamentos.Dispose();
			conn.Close();
		}
	}
Pelo que notei, ele não permite que se crie dois SqlDataReader simultâneos com a mesma conexão.

É isso mesmo? Como eu resolvo isso?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você está fechando o drDepartamentos, mas e o DataReader que você usa para carregar o 'e', este já está fechado?

 

Boa tarde gente.

Estou executando um SqlDataReader dentro de um RowDataBound e está exibindo o seguinte erro:

There is already an open DataReader associated with this Command which must be closed first.

Será que é porque ele executa o SqlDataReader em cada linha?

if (e.Row.RowType == DataControlRowType.DataRow){
   string strDepartamento = "";
   SqlCommand sqlDepartamentos = new SqlCommand("select txt_departamento from tbl_departamentos where id_departamentos in (" + e.Row.Cells[4].Text + ")", conn);
   SqlDataReader drDepartamentos = sqlDepartamentos.ExecuteReader();
   while(drDepartamentos.Read()){
	  strDepartamento += drDepartamentos["txt_departamento"].ToString();
   }
   drDepartamentos.Close();
   drDepartamentos.Dispose();
   sqlDepartamentos.Dispose();
}
Mas como vcs podem ver, eu estou fechando o dr.

Existe outra forma de executer uma query dentro do RowDataBound?

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim!

Segue o código que popula o grid:

try {
			conn.Open();
			SqlCommand sqlBusca = new SqlCommand(strBusca, conn);
			SqlDataReader drBusca = sqlBusca.ExecuteReader();
			gvCandidatos.DataSource = drBusca;
			gvCandidatos.DataBind();
			drBusca.Close();
			drBusca.Dispose();
			sqlBusca.Dispose();
			conn.Close();
		}catch(System.Data.SqlClient.SqlException ex){
			Response.Write(ex.Message);
		}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Opa!!! Descobri um jeito! Hehehe...

Ao invés de utilizar o SqlDataReader para popular o GridView eu utilizei um DataSet. Ficou assim:

Popular o grid:

conn.Open();
DataSet dsBusca = new DataSet();
SqlDataAdapter daBusca = new SqlDataAdapter(strBusca, conn);
daBusca.Fill(dsBusca, "Avaliacao");
gvCandidatos.DataSource = dsBusca.Tables["Avaliacao"];
gvCandidatos.DataBind();
daBusca.Dispose();
dsBusca.Dispose();
conn.Close();

Subquery da coluna:

//BUSCA OS DEPARTAMENTOS
string strDepartamento = "";
SqlCommand sqlDepartamentos = new SqlCommand("select txt_departamento from tbl_departamentos where id_departamentos in (" + e.Row.Cells[5].Text + ")", conn);
SqlDataReader drDepartamentos = sqlDepartamentos.ExecuteReader();
while(drDepartamentos.Read()){
   strDepartamento += drDepartamentos["txt_departamento"].ToString() + "<br />";
}
e.Row.Cells[5].Text = strDepartamento.ToString();
drDepartamentos.Close();
drDepartamentos.Dispose();
sqlDepartamentos.Dispose();
Não é permitido utilizar 2 ou mais SqlDataReader abertos ao mesmo tempo, pra isso se utiliza um DataSet que pode armazenar várias tabelas que poder ser acessadas por Table[indice].

Vlw!!! http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fuja dos DataSet :(

 

Sobre seu problema, é isso que vocês comentaram mesmo, a variável conn está sendo usada para popular a grid e dentro do RowDataBound. Como o DataReader trabalha conectado, quando você popula sua grid para cada linha ele vai executando o RowDataBoud que por sua vez vai fazer uma query no banco, mas a conn ainda está sendo usada para popular a Grid. Confusão :P Você precisa usar duas instâncias diferentes desta variável.

 

O que eu faria:

No RowDataBound, faça algo assim:

if (e.Row.RowType == DataControlRowType.DataRow){
   string strDepartamento = departamentosService.GetAll(e.Row.Cells[4].Text);
}

Ou seja, crie uma classe para fazer essa query, fica mais organizado, é reutilizavel, é mais fácil dar manutenção depois etc...

Dentro do método GetAll, você abre uma nova conexão e faz o que deve ser feito =)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Porque fugir do DataSet? :blink:

Tentei fazer o que você disse, mas acho que não segui o caminho correto. Suponha que o método que eu criei retorna a string que eu preciso:

public string retornaDepartamento(string ids) { 
   return "";
}
Depois crio o objeto e chamo o método:

Comum objComum = new Comum();
string strDepartamento = objComum.retornaDepartamento(e.Row.Cells[4].Text);
É isso mesmo? Onde aparece o GetAll?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Danilo,

 

DataSets são armazenadores de dados off-line, ou seja, copiam todo o conteúdo retornado pelo Command para a memória, no entanto, trabalhar com DataSets em Grid é muito mais fácil pois permite que você utilize o DataView para ordenar e filtrar registros, o que trará mais produtividade e talvez até mais performance (considerando a ordenação e filtro em runtime).

Compartilhar este post


Link para o post
Compartilhar em outros sites

É GetAll foi um exemplo, no seu caso está certo como você fez.

Mas o projeto sendo web, acho que não vai ter essas vantagens, a menos que ele guarde o dataset no ViewState.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O método que retorna o resultado ficou desta forma:

try {
			conn.Open();
			string strDepartamento = "";
			SqlCommand sqlDepartamento = new SqlCommand("select txt_departamento from tbl_departamentos where id_departamentos in (" + ids + ")", conn);
			SqlDataReader drDepartamento = sqlDepartamento.ExecuteReader();
			if (!drDepartamento.HasRows){
				return "Não consta";
			}else {
				//drDepartamento.Read();
				while (drDepartamento.Read()) {
					strDepartamento += drDepartamento["txt_departamento"] + "<br />";
				}
				return strDepartamento;
			}
			conn.Close();
			sqlDepartamento.Dispose();
			drDepartamento.Close();
			drDepartamento.Dispose();
		}catch(System.Data.SqlClient.SqlException ex){
			return ex.Message;
		}
Ficou certinho, mas se tiver uma forma de melhorar, sou todo ouvidos, hehehe...

Vlw gente!

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.