Desenvolvimento - ADO.NET
ADO.NET – Uma nova arquitetura para acesso a banco de dados
As bibliotecas tradicionais de acesso a banco de dados como ODBC e ADO da Microsoft, BDE da Borland e os componentes de acesso direto, como o IBExpress que acompanha o Delphi 5, foram desenvolvidos para acesso em rede local. Nestas bibliotecas, o programa estabelece uma conexão assim que é carregado e envia comandos através desta conexão, normalmente na linguagem SQL...
por Mauro Sant'AnnaAs bibliotecas tradicionais de acesso a banco de dados como ODBC e ADO da Microsoft, BDE da Borland e os componentes de acesso direto, como o IBExpress que acompanha o Delphi 5, foram desenvolvidos para acesso em rede local. Nestas bibliotecas, o programa estabelece uma conexão assim que é carregado e envia comandos através desta conexão, normalmente na linguagem SQL. Este esquema até que funciona em rede local, mas falha quando fazemos o acesso via Internet:
- A velocidade de comunicação na Internet é bem mais lenta que a rede local; o aplicativo fica lento e difícil de usar;
- A comunicação pode ser intermitente: a linha pode "cair" e ser restabelecida; uma biblioteca de acesso a banco de dados tradicional perde a conexão e o aplicativo tem que ser reinicializado;
- Podemos desejar trabalhar desconetcados por algum tempo, para economizar os impulsos da ligação telefônica.
- Podemos ter uma quantidade de usuários muito grande e até imprevisível acessando os sistemas via Internet; o acesso "via conexão" limita a quantidade simultânea de acesso.
O RDS da Microsoft resolve alguns dos problemas acima, mas ainda assim é apenas uma extensão do ADO, feito originalmente para acesso conectado.
O ADO.NET é uma biblioteca completamente nova para acesso a banco de dados, que enfatiza o acesso desconectado via Internet. A principal característica do ADO.NET é a introdução do componente DataSet. O DataSet é um banco de dados em memória. Os programadores Delphi podem encará-lo como um "CachedUpdates glorificado".
Componentes Adoxxx e SQLxxx
Existem dois conjuntos de componentes com funções muito parecidas:
- Componentes com nome iniciando em ADO: componentes genéricos para acesso com drivers OLE/DB, como Access, Microsoft SQL Server e Oracle.
- Componentes com nome iniciando em SQL: componentes exclusivos para acesso a Microsoft SQL Server, com melhor performance.
Os dois conjuntos de componentes têm essencialmente as mesmas características. Iremos abordar os componentes ADOXXX.
Figura 1: Esquema de funcionamento das classes ADO.NET
Componentes da biblioteca ADO.NET
O principal componente da arquitetura é o DataSet. Ele funciona como um “banco de dados em memória”, contendo tabelas, relacionamentos e “constraints”. Note que as tabelas aqui não são necessariamente as tabelas dos bancos de dados. Elas correspondem a comandos SQL armazenados em um ou mais DataSetCommand, que por sua vez pegam os dados em uma Connection. As mudanças no DataSet são passadas ao banco de dados via o DataSetCommand.
O DataSet pode também ser carregado a partir de arquivos XML ou de tabelas em memória.
Usando sem DataSet
Apesar do DataSet ser o principal componente da nova arquitetura, é possível usar a nova biblioteca sem ele; neste caso estaremos usando-a de maneira semelhante ao ADO tradicional.
Consulta
Para executar uma consulta, vamos precisar dos seguintes componentes:
- ADOConnection: Este objeto é associado a uma conexão ao banco de dados. Seu significado é praticamente o mesmo de um ADODB.Connection da versão anterior.
- ADOCommand: Este objeto é associado a um comando SQL. Ele é muito semelhante ao ADODB.Command que já existia na versão anterior, embora fosse pouco usado.
- ADODataReader: Este objeto é associado a um resultado de uma consulta ou stored procedure. Ele guarda alguma semelhança com um “Recordset forward-only/read only” da versão anterior.
Para quem estiver procurando algum correspondente ao ADODB.Recordset vai um aviso: ele não tem um correspondente direto.
ADOConnection
Este objeto gerencia uma conexão ao servidor de bancos de dados ou à fonte de dados. Cada cópia do objeto corresponderá a uma conexão distinta ao banco de dados. O controle de transação é feito a nível deste objeto.
- Abrindo uma conexão
- Para estabelecer uma conexão com a fonte de dados, primeiramente devemos criar um objeto ADOConnection. Veja um exemplo: ADOConnection Cnx = new ADOConnection(string de conexão); Observe que a string de conexão é qualquer “string de conexão ODBC”.
- Fechando uma conexão Quando você termina de trabalhar com seu banco de dados, você deve utilizar o método Close para liberar a conexão e recursos alocados. Você provavelmente irá usar um try/finally.
ADOCommand
Este objeto está associado a um comando SQL e a uma conexão. Veja um exemplo:
Listagem 1: Exemplo de uso do ADOCommand
ADOCommand Cmd = new AdoCommand(“select * from products”, Cnx);
ADODataReader
Este objeto está associado a um conjunto de resultado de uma query ou stored procedure. Ele é criado pelo método Execute do ADOCommand. Veja um exemplo:
Listagem 2: Exemplo de uso do ADODataReader
ADOCommand Cmd = new AdoCommand(...); ADODataReader DR; Cmd.Execute(out DR);
O ADODataReader contém vários métodos e propriedades para navegar no conjunto de resultado. Os principais são:
- Método Read(): Lê um registro, move o “apontador de registro” para o registro seguinte e retorna false se chegou ao final;
- GetXXX: Vários métodos que lêem o valor de um campo, dependendo de seu tipo, por exemplo, GetString(0).
Quando você termina de trabalhar com o ADODataReader, você deve utilizar o método Close para liberar os recursos alocados. Você provavelmente irá usar um try/finally.
Note algumas características importantes sobre o ADODataReader:
- Você só pode mover o registro corrente para frente e, ainda assim, na medida que estiver lendo;
- Não é possível mover o registro para posições arbitrárias;
- Não é possível alterar o conjunto de resultado.
O ADODataReader serve essencialmente para ler completamente o resultado de uma query SQL SELECT. Esta é uma situação bastante comum durante o desenvolvimento.
Exemplo completo
O programa a seguir mostra o resultado de uma consulta em uma página Web usando o Visual Studio.NET em um aplicativo ASP.NET:
Listagem 3: Consulta em uma página web
namespace BD1 { using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.Data.ADO; /// <summary> /// Summary description for WebForm1. /// </summary> public class WebForm1 : System.Web.UI.Page { public WebForm1() { Page.Init += new System.EventHandler(Page_Init); } void Mostra () { Label1.Text = ""; string CmdStr = "SELECT ProductName, ProductType FROM Products"; ADOConnection Cnx = new ADOConnection (@"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=\\mas9\dados\AdvWorks.mdb;"); Cnx.Open(); try { ADOCommand Cmd = new ADOCommand(CmdStr, Cnx); ADODataReader DR; Cmd.Execute(out DR); try { while (DR.Read()) { Label1.Text += DR.GetString(0) + " - " + DR.GetString(1) + "<br>"; } } finally { DR.Close(); } } finally { Cnx.Close(); } } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Mostra(); // // Evals true first time browser hits the page // } } protected void Page_Init(object sender, EventArgs e) { // // CODEGEN: This call is required by the ASP+ // Windows Form Designer. // InitializeComponent(); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler (this.Page_Load); } } }
Note o seguinte:
- Incluímos a linha “using System.Data.ADO;” para “abrir” o namespace que contém as declarações do ADO.NET, facilitando o seu uso.
- A exibição dos dados é feita em um componente Label.
- O código de exibição é chamado quando a página é carregada pela primeira vez.
Veja a saída no navegador:
Figura 2: Dados listados
Comandos de alteração
Até agora sempre vimos consultas (comandos SQL SELECT). Podemos facilmente enviar comandos de alteração (INSERT, UPDATE e DELETE). Para isto, usaremos o mesmo componente ADOCommand visto anteriormente, mas chamando o método ExecuttNonQuery(). Veja um fragmento do exemplo BD5:
Listagem 4:
decimal Aumento = TextBox1.Text.ToDecimal() / 100 + 1; string CmdStr = "UPDATE Products set UnitPrice = UnitPrice * " + Aumento.ToString(); ADOCommand Cmd = new ADOCommand(CmdStr, adoConnection1); Cmd.ExecuteNonQuery();
Conclusão
O ADO.Net é uma biblioteca bastante poderosa para acesso a bancos de dados. Ela resolve problemas concretos criados quando precisamos acessar bancos de dados via Internet.