Jump to content
Phaster

fazer com que uma dropdown list execute queries e faça databind a uma gridview

Recommended Posts

Phaster

boas,

neste momento estou a desenvolver uma aplicação de intranet com páginas departamentais, estas páginas terão todas o mesmo layout e mesmas funcionalidades, sendo elas:

- execução de queries e visualização do resultado das mesmas na única gridview que tenho (não funca com dropdown mas com botões a executar a query sim)

- exportação dos resultados das queries para excel (funciona com os botões)

- envio de emails com os resultados num anexo em excel (funciona com os botões)

no entanto, quando a intranet for disponibilizada aos colaboradores um gajo já sabe que vão chover pedidos do género "eu queria era ver a query tal" ou "eu quero que esta query também me mostre isto" etc, para nós de IT não estarmos sempre a recorrer ao visual studio de cada vez que alguém quer editar/inserir uma nova query, eu pensei em criar uma tabela que contenha todas as query strings que nós que queremos, assim só tenho de criar uma página de administração com um simples INSERT/UPDATE, colar a query numa textbox e aquilo insere ou edita conforme um gajo queira.

a tabela (rot_dep) tem a seguinte estrutura:

jk8h4jdttk4f.png

em relação a estrutura da página em si, o código é o seguinte:

<asp:Content ID="rightcontent" ContentPlaceHolderID="rightcontent" Runat="Server">
<form id="form1" runat="server">
<asp:DropDownList ID="DropDownList1" runat="server" onselectedindexchanged="DropDownList1_SelectedIndexChanged" DataSourceID="SqlDataSourcedrop" DataTextField="name" DataValueField="">
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSourcedrop" runat="server" ConnectionString="<%$ ConnectionStrings:DB_testeConnectionString %>"
 SelectCommand="SELECT [name] FROM [rot_dep] where department = 'Compras'"></asp:SqlDataSource>
</form>
</asp:Content>


<asp:Content ID="rightcontentdown" ContentPlaceHolderID="rightcontentdown" Runat="Server">

<asp:GridView ID="GridView1" runat="Server" AutoGenerateColumns="true"></asp:GridView>

</asp:Content>

o código da dropdown é o seguinte, de salientar que para em cada página departamental o utilizador só vai conseguir seleccionar as queries definidas para o seu departamento:

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
 DataTable dta = new DataTable();
 SqlConnection Connection = null;
 SqlCommand Command = null;
 string ConnectionString = ConfigurationManager.ConnectionStrings["DB_testeConnectionString"].ConnectionString;
 string CommandText = "SELECT query"
					 + "FROM rot_dep"
					 + "WHERE name = @query 1 ";
 Connection = new SqlConnection(ConnectionString);
 Connection.Open();
 Command = new SqlCommand(CommandText, Connection);
 Command.Parameters.Add(new SqlParameter("@query 1", DropDownList1.SelectedItem.Text));
 var results = Command.ExecuteReader();
 SqlDataAdapter sqlDa = new SqlDataAdapter(Command);

 sqlDa.Fill(dta);
 GridView1.DataSource = dta;
 GridView1.DataBind();
 Command.Dispose();
 Connection.Close();

}

ora este código não me dá erro nenhum e eu só consigo efectivamente escolher as queries afectas ao departamento que defini, no entanto, não acontece nada quando escolho uma query na dropdown, agora não sei se não está a ler a querystring presente na tabela da BD ou se não está a fazer o databind

agradecia alguma ajuda sff

Share this post


Link to post
Share on other sites
jota_wa

Boas

Tenho 99% de certeza que o teu problema está no nome do parâmetro "@query 1",porque não podes ter espaços nos nomes.Tira o "1" da "@query" e testa de novo.

Cumps

Share this post


Link to post
Share on other sites
Phaster

boas,

fiz agora isso e acontece a mesma coisa, será que na bd as querystrings têm de estar entre aspas?

Share this post


Link to post
Share on other sites
pikax

o problema esta na string da query!

string CommandText = "SELECT query FROM rot_dep WHERE name = @query1 ";


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
jota_wa

boas,

fiz agora isso e acontece a mesma coisa, será que na bd as querystrings têm de estar entre aspas?

Boas

Nop,é mesmo na própria query o problema,como o pikax refere em baixo.

o problema esta na string da query!

string CommandText = "SELECT query FROM rot_dep WHERE name = @query1 ";

Porque não estás a usar espaços entre as colunas e o "FROM" e a tabela e o "WHERE".

Cumps

Share this post


Link to post
Share on other sites
Phaster

agora tenho o código assim e o datavaluefield da dropodown está vazio:

string CommandText = "SELECT query FROM rot_dep WHERE name = @query";

continua a não acontecer nada

e fiz o seguinte:

  • sem datavaluefield na dropdown, fiz enable autopostback, ao seleccionar a query na dropdown recebo o seguinte erro "There is already an open DataReader associated with this Command which must be closed first." na linha

sqlDa.Fill(dta);

  • com "name" no datavaluefield da dropdown e com autopostback enabled, ao seleccionar a query recebo o erro "There is already an open DataReader associated with this Command which must be closed first" na mesma linha mencionada acima
  • com "name" no datavaluefield da drop e com autopostback, se eu apagar a linha:
    var results = Command.ExecuteReader();
    

    , quando escolho a query ele mostra na gridview a querystring armazenada na bd

EDIT:

acrescentei mais uma coluna na tabela para outra funcionalidade.

p4k5k9kte36c.png

após experimentar um bocado, o código é o seguinte, continuo conseguir com a selecção mostre a querystring na gridview em vez de ler a query e mostrar os dados que ela retorna

DataTable dta = new DataTable();
 SqlConnection Connection = null;
 SqlCommand Command = null;
 string ConnectionString = ConfigurationManager.ConnectionStrings["DB_testeConnectionString"].ConnectionString;
 string CommandText = "SELECT query FROM rot_dep WHERE name = @query";
 Connection = new SqlConnection(ConnectionString);
 Connection.Open();
 Command = new SqlCommand(CommandText, Connection);
 Command.Parameters.Add(new SqlParameter("@query", DropDownList1.SelectedItem.Text));
 var results = Command.ExecuteScalar();
 SqlDataAdapter sqlDa = new SqlDataAdapter(Command);
 sqlDa.Fill(dta);
 if (dta.Rows.Count > 0)
 {
	 GridView1.DataSource = dta;
	 GridView1.DataBind();
 }

 Command.Dispose();
 Connection.Close();

agora aproveito para deixar a seguinte questão, como faço com que o evento de selecção na dropdown além de ler a query na coluna "query", mostre os dados que a mesma retorna na gridview e popule uma label com a descrição na query? tenho de chamar outro método separado para popular a label?

Edited by Phaster

Share this post


Link to post
Share on other sites
munkbozz

SqlDataReader - É usado para obter dados.

ExecuteScalar - Retorna o número de rows de uma query.

ExecuteNonQuery - Queries do tipo Insert, Update, Delete.

var results = Command.ExecuteScalar();

if (dta.Rows.Count > 0)

{

GridView1.DataSource = dta;

GridView1.DataBind();

}

Poderás tentar:

int results = (int)Command.ExecuteScalar();
if(results > 0)
{
...
}

agora aproveito para deixar a seguinte questão, como faço com que o evento de selecção na dropdown além de ler a query na coluna "query", mostre os dados que a mesma retorna na gridview e popule uma label com a descrição na query? tenho de chamar outro método separado para popular a label?

Usa o evento SelectedIndexChanged no teu ComboBox.

Share this post


Link to post
Share on other sites
Phaster

obrigado, tentei o seguinte mas dá erro, será que devia estar a usar o datareader, uma vez que quero obter os dados que as queries, quando corridas, retornam? de salientar que o data type da coluna "query" é nvarchar(500)

vl9in3cnemj.png

duas coisas:

  • preciso de ter o autopostback activado ou não?
  • mesmo depois de ter pesquisado sobre binding de labels e textbox's, não estou a ver como hei-de usar o evento de selecção na dropdown, para passar 2 queries (ler a que está na coluna "query", mostrar os resultados da mesma na gridview e mostrar os registos na coluna "description" na label)

Edited by Phaster

Share this post


Link to post
Share on other sites
munkbozz

Então se queres obter os dados terás de usar o SqlDataReader, isto funciona da seguinte forma:

SqlDataReader reader;

try
{
reader = cmd.ExecuteReader();
{
while (reader.Read()) { var id = (int)reader["nome_da_coluna"]; var nome = reader["nome_da_coluna"]; }
}
reader.Close();
 }
}

catch (SqlException ex) { MessageBox.Show(ex.Message); }

Se estiveres com problemas na leitura dos dados, confere este website contêm os respectivos tipos de dados em C# que deves usar na leitura de dados SQL.

- http://msdn.microsoft.com/en-us/library/cc716729.aspx

Quanto ao erro:

int results = (int)Command.ExecuteScalar();

Não sei o que se está a passar para que isso aconteça, mas podes sempre tentar usar

(Int32)

.

Edited by munkbozz

Share this post


Link to post
Share on other sites
Phaster

boas, muito obrigado pela tua ajuda, eu sei que estou a ser um chato do caraças

depois de ver o teu post fui descobrir como adaptava o código para a minha situação e fiquei com o seguinte:

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
   {
    SqlConnection newconnection = new SqlConnection(GetConnectionString());
    SqlCommand qwcommand = newconnection.CreateCommand();
    qwcommand.CommandText = "SELECT query FROM rot_dep WHERE name = @query";
    newconnection.Open();
    SqlDataReader querySqlDataReader = qwcommand.ExecuteReader();
    try
    {
	    querySqlDataReader = qwcommand.ExecuteReader();
	    {
		    while (querySqlDataReader.Read())
		    {
			    var id = (int)querySqlDataReader["query"];
			    var name = querySqlDataReader["query"];
		    }
		    querySqlDataReader.Close();
	    }

    }
    finally
    {
	    qwcommand.Dispose();
	    newconnection.Close();
    }
   }

que me dá o seguinte erro:

wd5v9d6jnizx.png

já agora aproveito para deixar a seguinte questão, onde meto o código para fazer databind?

Share this post


Link to post
Share on other sites
munkbozz

Oh amigo então tu andas-me cada vez a cortar mais código, falta-te especificar o parâmetro '@query'.

Command.Parameters.AddWithValue("@query", DropDownList1.SelectedItem.ToString());

O bind podes fazer depois de ler os dados eu aconselho colocares num procedimento diferente para não parecer muito confuso, se precisares de usar uma váriavel acessivel pelo SqlDataReader declara uma váriavel do tipo privado fora do escopo.

Se com 'bind' queres dizer passar para uma tabela usas o objecto DataGridView.

private void _exemplo()
{
string db = nome_da_base_de_dados;
SqlCommand cmd = new SqlCommand();
SqlDataAdapter _adpater = new SqlDataAdapter();
DataSet _set = new DataSet();
cmd = Connection.CreateCommand();
cmd.CommandText = "a_tua_query";
_adpater.Fill(_set, db);
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = _set;
dataGridView1.DataMember = db;
}

Em relação ao Dispose do objecto eu acho que não seja necessário neste contexto.

Edited by munkbozz

Share this post


Link to post
Share on other sites
Phaster

epá, tens razão, mas eu depois apercebi-me e declarei o parametro, no entanto recebo o seguinte erro

8yttmxfdd2k.png

estás a dizer que posso criar um método à parte para fazer o bind à gridview, no entanto, onde é que chamo o método? no "finally" antes de fechar a conexão?

Edited by Phaster

Share this post


Link to post
Share on other sites
munkbozz

Não, podes criar um outro procedimento (vamos dizer outra void) e depois chamar essa void aquando do evento SelectedIndexChanged.

Esse erro que estas a ter, não sei a razão, pois para mim esse cast funciona. Como te disse antes experimenta usar.

(Int32)

Este cast * (int) * que te tinha dado não deveria apresentar qualquer erro.

Edited by munkbozz

Share this post


Link to post
Share on other sites
Phaster

pois, mesmo assim não funca, noutro lado disseram que estou a fazer cast para int de algo que não é int, se assim for e segundo o link que tu puseste lá para cima, tenho de fazer o cast para "GetSqlString"? se sim, como?

Share this post


Link to post
Share on other sites
munkbozz

pois, mesmo assim não funca, noutro lado disseram que estou a fazer cast para int de algo que não é int, se assim for e segundo o link que tu puseste lá para cima, tenho de fazer o cast para "GetSqlString"? se sim, como?

Não sei amigo, o cast que te disponibilizei funciona perfeitamente comigo. Tenta usar o Convert.ToInt32, ToInt16 ou de outra forma, isto varia com o tipo de dado que tens para essa coluna na tua tabela.

Share this post


Link to post
Share on other sites
Phaster

muito obrigado pela ajuda, no entanto, agora numa primeira fase de implementação vamos optar por usar views e quando alguém quiser uma nova query, um gajo vai ao visual studio e mexe no código, se mais tarde seguirmos a abordagem deste tópico cá voltarei

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.