C# - Acessando e obtendo dados com DataReader
Este artigo mostra como acessar um banco de dados e exibir as informações das tabelas usando ADO .NET, mais especificamente a classe DataReader.
A classe DataReader fornece funções similares aos cursores SQL, os quais não são atualmente suportados na plataforma .NET. Dessa forma ela é usada para retornar um fluxo de dados e somente-para-frente e somente-leitura de uma fonte de dados de forma muito eficiente.
Os DataReaders são apropriados quando você precisa simplesmente exibir o resultado de uma consulta em cenários onde as informações não precisam ser atualizadas nem persistidas através de múltiplas requisições.
A classe DataReader é um componente ADO .NET que possui diversos componentes para acesso e manipulação de dados e que possui dois componentes principais:
A seguir temos uma figura mostrando os componentes da arquitetura ADO .NET:
Neste exemplo eu vou acessar o banco de dados Northwind.mdf do banco de dados SQL Server e exibir informações em um projeto Windows Forms usando a linguagem C#.
Este é um artigo para iniciantes e aborda o acesso a dados, a utilização da classe DataReader em um projeto Windows Forms.
Para criar o projeto deste artigo eu vou usar o Visual C# 2010 Express Edition (ele é gratuito).
Abra o Visual C# 2010 Express e crie um novo projeto do tipo Windows Forms Application com o nome acesso_DataReader;
No exemplo deste artigo vamos criar uma interface que permite que usuários efetuem consultas na tabela Products do banco de dados Northwind usando uma consulta com parâmetros e a classe DataReader.
Vamos definir a interface com o usuário no formulário form1.vb conforme o leiaute da figura abaixo:
Os componentes usados a partir da ToolBox foram:
O projeto vai funcionar assim:
A seguir temos a imagem mostrando a tela principal do programa exibindo informações dos produtos da tabela Products do banco de dados Northwind.mdf;
Observe que basta o usuário digitar um caractere para que produtos iniciados pelo caractere sejam exibidos e que também exibidos o total de produtos localizados para a consulta.
Vejamos como podemos implementar o código para realizar tal tarefa.
Iniciamos definindo os namespaces usados no projeto:
using System;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Configuration;
Os namespaces System.Data e System.Data.SqlClient nos dão acesso as classes de acesso a dados usadas no projeto : SqlConnection, SqlCommand, SqlDataReader e a propriedade ConnectionState;
O namespace Configuration permite usarmos a classe ConfigurationManager para obter a string de conexão do arquivo App.Config que é exibido abaixo:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> </configSections> <connectionStrings> <add name="acesso_DataReader.Properties.Settings.NORTHWNDConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\dados\NORTHWND.MDF;Integrated Security=True;Connect Timeout=30;User Instance=True" providerName="System.Data.SqlClient" /> </connectionStrings> </configuration> |
Além de definir o namespace devemos incluir uma referência no projeto a System.Configuration para isso clique com o botão direito do mouse sobre o nome do projeto e selecione Add Reference;
Em seguida selecione na aba .NET a opção System.Configuration e clique Ok;
Agora vamos definir as variáveis objeto usadas no projeto declarando-as logo após no início do formulário form1::
SqlDataReader rdr =
null;
SqlConnection con = null;
SqlCommand cmd = null;
Crie a rotina getConexaoBD no formulário form1
que vai obter a string de conexão do arquivo App.Config
usando a classe ConfigurationManager, criar uma nova conexão e
retorna a conexão criada:
private SqlConnection getConexaoBD() { //obtem a string de conexão do App.Config e retorna uma nova conexao string strConexao = ConfigurationManager.ConnectionStrings["acesso_DataReader.Properties.Settings.NORTHWNDConnectionString"].ConnectionString; return new SqlConnection(strConexao); } |
No evento Click do botão para localizar produtos , ao lado da caixa de texto, defina o seguinte código:
private void btnLocalizar_Click(object sender, EventArgs e) { try { con = getConexaoBD(); con.Open(); // define o command com a consulta dada e associa a conexão string sql = "SELECT ProductID, ProductName, UnitPrice" + " FROM Products" + " WHERE (ProductName LIKE @nomeProduto)" + " ORDER BY ProductID"; cmd = new SqlCommand(sql); cmd.Connection = con; // define o parâmetro cmd.Parameters.Add(new SqlParameter( "@nomeProduto", // o nome do produto System.Data.SqlDbType.NVarChar, // o tipo do parametro 20, // o tamanho do parametro "ProductName")); // o nome da coluna // Preenche o parametro com o valor obtido do campo texto cmd.Parameters["@nomeProduto"].Value = txtProduto.Text + "%"; // Executa a cosulta rdr = cmd.ExecuteReader(); // limpa o listbox lbProdutos.Items.Clear(); //define o total de registros como zero int nuReg = 0; //percorre o leitor e exibe os valores no listbox while (rdr.Read()) { lbProdutos.Items.Add(rdr["ProductID"].ToString() + " - " + rdr["ProductName"].ToString() + " - " + rdr["UnitPrice"].ToString()); nuReg++; } //exibe o total de registros obtidos lbltotal.Text = nuReg.ToString() + " Produtos"; } catch (Exception ex) { // mensagem de erro MessageBox.Show(ex.Message); } finally { // fecha os objetos datareader e connection if (rdr != null) rdr.Close(); if (con.State == ConnectionState.Open) con.Close(); } } |
Vamos entender o código usado:
1- Obtemos uma nova conexão usando a função getConexaoBD() e a abrimos:
con = getConexaoBD();
con.Open();
2- Definimos uma instrução SQL para retornar o código, nome e preço do produto onde o nome do produto deverá ser igual ao nome informado pelo usuário. Aqui criarmos uma consulta parametrizada onde o parâmetro foi definido como @nomeProduto. Note o sinal @ no início do nome.
A cláusula LIKE permite efetuar uma consulta irrestrita:
Usando a cláusula LIKE | |||||||||||||
As vezes os dados que você
está desejando filtrar não têm uma ocorrência exata, ou você pretende
realizar uma busca mais irrestrita. Para isso devemos usar a cláusula
LIKE. Supondo que desejamos filtrar todos os alunos que
tenham o nome começado pelas letrar Jos, Através da
cláusula LIKE podemos inserir as letras desejadas e a SQL fará uma busca
parcial pela string informada: Algo como:
Isto retornará os possíveis nomes: José , Josué, Josimar, Josias, etc... Note que usamos o sinal de porcentagem (%) que funciona como um coringa , substituindo os demais caracteres. A seguir listamos abaixo as principais ocorrências :
|
// define o command com a consulta dada e associa a conexão
string sql = "SELECT ProductID, ProductName, UnitPrice" +
" FROM Products" +
" WHERE (ProductName LIKE @nomeProduto)" +
" ORDER BY ProductID";
cmd = new SqlCommand(sql);
cmd.Connection = con;
Definimos um objeto Command para a instrução sql definida e especificamos
a conexão onde o comando será usado.
3- Definimos o parâmetro a ser usado , seu nome, tipo de dados, tamanho e nome da coluna sobre o qual irá atual e incluímos na coleção Parameters:
// define o parâmetro
cmd.Parameters.Add(new SqlParameter(
"@nomeProduto",
// o nome do produto
System.Data.SqlDbType.NVarChar, // o tipo
de dados do parametro
20, // o tamanho do parametro
"ProductName")); // o nome da coluna
// Preenche o parametro com o valor obtido do campo texto
cmd.Parameters["@nomeProduto"].Value = txtProduto.Text + "%"
Ao definir o valor do parâmetro obtemos o valor informado na caixa de texto
txtProduto e acrescentamos o curinga '%' a final do texto digitado
para ser usado com a cláusula LIKE que já explicamos acima.
4- Executamos a consulta obtendo um DataReader (rdr), e preenchemos o controle ListBox com as informações obtidas:
// Executa a cosulta
rdr = cmd.ExecuteReader();
// limpa o listbox
lbProdutos.Items.Clear();
//define o total de registros como zero
int nuReg = 0;
//percorre o leitor e exibe os valores no listbox
while (rdr.Read())
{
lbProdutos.Items.Add(rdr["ProductID"].ToString() +
" - " + rdr["ProductName"].ToString() + " - " + rdr["UnitPrice"].ToString());
nuReg++;
}
//exibe o total de registros obtidos
lbltotal.Text = nuReg.ToString() + " Produtos";
Para obter o total de registros tivemos que usar um artifício. Quando você usa a classe SqlDataReader ou OleDbDataReader , nao existe nenhuma propriedade RecordCount para indicar quantos registros estão sendo obtidos
O objeto DataReader ou a
fonte de dados geralmente sabe quantos registros
estão sendo obtidos até que o último registro seja enviado para o
cliente.
Para contornar este problema, use um
dos seguintes métodos:
Dessa forma cumprimos nosso objetivo e obtemos os registros desejados usando um DataReader. Para melhorar o código sugiro que você crie uma camada e remova o código de acesso a dados do formulário usando as boas práticas.
Pegue o projeto completo aqui: acesso_DataReader.zip
Eu sei é apenas C#, mas eu gosto...
C# , Simples, simples assim...
Referências: