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'Anna



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. 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.

 Esquema de funcionamento das classes ADO.NET

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:

 Dados listados

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.

Mauro Sant'Anna

Mauro Sant'Anna - Mauro tem mais de 20 anos de experiência no desenvolvimento de software, com produtos publicados no Brasil, Portugal e Estados Unidos, além de extensa experiência em treinamento e consultoria no desenvolvimento de software, tanto criando material como ministrando cursos.
Mauro é um "Microsoft Most Valuable Professional" (MVP - www.microsoft.com/mvp), “Microsoft Regional Director” (RD - www.microsoft.com/rd), membro do INETA Speaker’s Bureau (www.ineta.org) e possui as certificações MCP, MCSA (Windows 2000/2003), MCAD (C# e VB), MCDBA, MCSE (Windows 2000/2003).
Sua empresa, a M. A. S Informática (www.mas.com.br), treinou centenas de turmas em desenvolvimento de software nos últimos anos.