C# - ADO .NET para iniciantes IV - DataReader (SqlDataReader)
Esta chegando agora ???
Então acompanhe os primeiros artigos:
O objeto DataReader da ADO .NET pertence ao namespace System.Data e apresenta as seguintes especificidades:
Você vai encontrar na leitura técnica a designação de que o um DataReader é forward-only (somente para frente) e read-only (somente-leitura).
O resultado gerado por um DataReader é retornado pela execução da consulta e é armazenada no buffer da rede no cliente até que seja requisitado através do método Read().
Resumindo as funcionalidades do DataReader:
- É um objeto somente leitura e para frente, ou
seja, não você não pode navegar aleatoriamente;
- Opera conectado ao banco, assim, enquanto estivermos utilizando-o para
obter os dados do banco, estaremos com a conexão do banco aberta;
- Opera apenas com uma tabela por vez; você deve configurar a string SQL para
a primeira tabela, conectar no banco, coletar suas informações e desconectar do
banco. Para a segunda tabela você deverá repetir o processo;
Nota: A conexão utilizada pelo
DataReader deve ser aberta e fechada manualmente.(exceto quando você informa que
ela deverá ser fechada de forma automática usando a enumeração CommandBehavior.CloseConnection)
Você
deve usar um DataReader em sua aplicação quando:
Nota: O DataAdapter usa o DataReader par preencher o DataSet. Desta forma , o desempenho ganho pela utilização do DataReader é que você salva na memória os dados que o DataSet irá consumir. |
O roteiro básico para utilização de um objeto DataReader é o seguinte:
Abaixo temos um exemplo bem básico do código usando SqlDataReader:
using System.Data; using System.Data.SqlClient; string connString = "Data Source=server;Initial Catalog=database;Persist Security Info=True;User ID=sa;Password=xxx" SqlConnection adoConn = new SqlConnection(connString); adoConn.Open(); // novo command string sql = "SELECT * FROM Tabela"; SqlCommand adoCmd = new SqlCommand(sql, adoConn); SqlDataReader adoDR = adoCmd.ExecuteReader(); if (adoDR.HasRows) { while (adoDR.Read()) { Response.Write(adoDR["0"].ToString()); } } adoDR.Close(); adoDR.Dispose(); adoCmd.Dispose(); adoConn.Close(); adoConn.Dispose(); |
Observe as linhas em negrito onde temos:
1-) A criação de um objeto SqlCommand usando uma instrução SQL e a conexão
SqlCommand adoCmd = new SqlCommand(sql, adoConn);
2-) A criação de um objeto SqlDataReader e utilização do método ExecuteReader() do objeto SqlCommand;
SqlDataReader adoDR = adoCmd.ExecuteReader();
3-) Utilização do método Read() para ler o resultado
while (adoDR.Read())
Veja a seguir outra forma de obter o mesmo resultado:
using
System.Data.SqlClient; public void exibirDados() { string consulta = "SELECT * FROM Tabela"; SqlConnection conexao = new SqlConnection("conString"); SqlCommand comando = new SqlCommand(consulta, conexao); SqlDataReader dr = null; try { conexao.Open(); dr = comando.ExecuteReader(); while (dr.Read()) { Console.WriteLine(dr.GetString(1)); } } catch{ Console.WriteLine("Erro."); } finally { dr.Close(); conexao.Close(); } } |
Observe que abrimos uma conexão com a fonte de dados e após executar a consulta usando o método ExecuteReader() atribuímos o resultado ao objeto SqlDataReader dr.
Para exibir o resultado usamos um laço While onde percorremos o SqlDataReader usando o método Read(), este método avança sempre para o próximo registro e retorna True enquanto existir um registro a ser lido.
Para ler os valores retornados podemos usar o nome da coluna, o seu índice ou os métodos Get do SqlDataReader:
O objeto
SqlDataReader possui alguns métodos para obter os dados
das colunas como: GetString(), GetValue(), getDateTime(),
GetDouble(), GetChar(), GetGuid(), GetInt16(),
GetInt32(), etc.. Cada um destes métodos usa um valor inteiro como índice baseado em zero e representa a coluna a ser obtida. Assim dr.GetString(0) retorna o valor da primeira coluna. Para detalhes veja o link: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader_members.aspx |
No primeiro exemplo antes de iniciarmos o laço e a leitura do DataReader usamos o método HasRows que é usado para verificar se existem linhas no DataReader, se existir ele retorna True, se não retorna False e neste caso nem iniciaremos a leitura do mesmo.
O enumerador CommandBehavior possui o item CloseConnection() que pode ser usado com o método ExecuteReader do objeto SqlCommand() da seguinte forma:
dr = comando.ExecuteReader(CommandBehavior.CloseConnection)
neste caso estamos passando o CommandBehavior.CloseConnection() como parâmetro para o objeto ExecuteReader e com isso não temos a necessidade de fechar a conexão explicitamente com a fonte de dados, pois ao percorrer os dados o próprio DataReader irá fechar a conexão quando o método Close() do DataReader for chamado.
Veja um exemplo usando este recurso:
using
System.Data.SqlClient; public void exibirDados(){ SqlConnection conexao = new SqlConnection("connString"); SqlCommand comando = new SqlCommand("SELECT * FROM TABELA", conexao); SqlDataReader dr=null; try { conexao.Open(); dr = comando.ExecuteReader(CommandBehavior.CloseConnection); while (dr.Read()) { Console.WriteLine(dr.GetString(1)); } } catch (Exception ex) { Console.WriteLine("Erro."); } finally { dr.Close(); } } |
Observe que neste caso não fechamos a conexão explicitamente com o banco de dados. Para verificar se a conexão ainda esta aberta podemos verificar o seu estado usando o código a seguir:
if (conexao.State !=
ConnectionState.Closed)
conexao.Close();
Exemplo prático usando DataReader
No exemplo a seguir vamos criar uma aplicação C# com uma interface bem simples que permite aos usuários procurar pelo nome dos produtos na tabela Products do banco de dados Northwind.mdf. Este exemplo usará o seguintes recursos:
Abra o Visual C# Express Edition e crie um novo projeto do tipo Windows Application com o nome uDataReader;
A seguir no formulário padrão inclua os controles : Label, Button - btnProcurar , ListBox - lbDados e TextBox - txtcriterio conforme o leiaute abaixo:
Agora defina o namespace : using System.Data.SqlClient;
No evento Click do botão de comando Procurar insira o seguinte código:
private void btnProcurar_Click(object sender, EventArgs e) { //define os objetos DataReader, Connection e Command SqlDataReader sqldr = null; SqlConnection con = null; SqlCommand cmd = null; try { // Abre a conexão com o banco de dados Northwind no SQL Server 2005 Express // .\SQLExpress é o nome default do servidor // initial Catalog - indica o banco de dados // String usando Windows Authentication (Trusted Connection): string ConnectionString = "Data Source=.\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI"; con = new SqlConnection(ConnectionString); con.Open(); // define um comando para selecionar os produtos e preços da tabela products string CommandText = "SELECT ProductName,UnitPrice " + "FROM Products " + "WHERE (ProductName LIKE @criterio)"; //associa comando a conexão cmd = new SqlCommand(CommandText); cmd.Connection = con; // Define o parâmetro @criterio e seu tipo de dados cmd.Parameters.Add( new SqlParameter( "@criterio", // o nome do parametro System.Data.SqlDbType.NVarChar, // o tipo de dado SqlDbType 40, // o tamanho do parametro "ProductName")); // o nome da coluna na tabela a qual se aplica // Preenche o valor do parâmetro com o texto informado // na caixa de texto : txtcriterio cmd.Parameters["@criterio"].Value = txtcriterio.Text+"%"; // executa a consulta sqldr = cmd.ExecuteReader(); lbDados.Items.Clear(); // preenche o listBox com os valores retornados // usa o método read() para percorrer o datareader while (sqldr.Read()) { lbDados.Items.Add(sqldr["ProductName"].ToString() + " - " + sqldr["UnitPrice"].ToString()); } } catch (Exception ex) { // exibe mensagem de erro MessageBox.Show(ex.Message); } finally { // fecha o data reader e a conexão if (sqldr != null) sqldr.Close(); if (con.State == ConnectionState.Open) con.Close(); } } |
Note que estamos usando o parâmetro @criterio para receber o valor informado na caixa de texto na instrução de comando SQL :
SELECT ProductName,UnitPrice FROM Products WHERE (ProductName LIKE @criterio)"
;Ao atribuir o valor ao parâmetros incluímos o caractere % ao final do valor digitado: cmd.Parameters["@criterio"].Value = txtcriterio.Text+"%";
Após executar o comando via método ExecuteReader() percorremos o DataReader com o método Read() e obtemos os valores usando a sintaxe: sqldr["ProductName"].ToString() + " - " + sqldr["UnitPrice"].ToString()
O resultado para a letra C pode ser visto abaixo:
Pegue o projeto completo aqui: uDataReader.zip
Usando uma Stored Procedure
Podemos também gerar um DataReader executando uma stored procedure. Supondo que você tenha uma stored procedure criada no banco de dados com o nome listaClientes que obtêm os clientes para um determinado id.
O código usado para definir o comando e passar o parâmetro pode ser escrito assim:
1 SqlCommand
storedProcCommand = new SqlCommand
("listaClientes", con);
2 storedProcCommand.CommandType = CommandType.StoredProcedure;
3 storedProcCommand.Parameters.Add("@ID",clienteID);
4 SqlDataReader reader =
storedProcCommand.ExecuteReader();
5 while (reader.Read())
{//}
- Na primeira linha construímos o objeto
SqlCommand com o nome da stored procedure usando a conexão com o
banco de dados;
- Na linha 2 o objeto Sqlcommand define que estará
executando uma stored procedure;
- Na linha 3 incluímos o parâmetro no objeto
SqlCommand. Observe o uso do símbolo @ usado para identificar um
parâmetro no SQL Server.
- Na linha 4 usamos o método ExecuteReader()
para executar a stored procedure e retornar um DataReader;
- Na linha 5 iniciamos a leitura do DataReader;
Lembrete:
Um
DataReader é sempre mais rápido que um DataSet ??? A resposta é : DEPENDE... A
vantagem do DataReader e não ter que carregar todo o conteúdo
da tabela em memória, e retornar os registros à medida
que são disponibilizados pelo banco de dados; enquanto que o DataSet aguarda o
fim da execução da consulta para prosseguir a execução. O DataReader carrega na memória apenas
o registro atual. Por isso, não é possível acessar registros anteriores.(Ele
é forward-only lembra-se ?) Ora !! neste caso é melhor um DataSet pois exige menos código para ser tratado. |
Concluímos assim esta apresentação sobre o objeto DataReader e sua utilização com o SqlDataReader.
No próximo artigo irei falar sobre o objeto SqlDataAdapter e DataSet.
Eu sei é apenas ADO .NET, mas eu gosto...
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
|
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências: