ADO .NET - Usando as interfaces ADO .NET

 Hoje vamos veremos como simplificar o seu código de acesso a dados usando as interfaces ADO .NET.

Aqui estou eu em pleno século XXI falando sobre ADO .NET.  Tem cabimento isso ? Tem sim...

Na verdade, para quem esta chegando agora, e precisa acessar um banco de dados relacional de maneira simples e eficaz ainda tem a ADO .NET como uma boa opção.

Se você consultar a documentação da MSDN vai encontrar exemplos usando ADO .NET que mostram apenas as classes concretas dos provedores. Acontece que é muito mais fácil de trabalhar com ADO .NET se você usar as Interfaces - IDbConnection, IDbCommand, IDataReader, IDataParameter.

Todos os provedores do ADO.NET implementam essas interfaces, portanto, um bom grau de independência do provedor pode ser obtido codificando as interfaces em vez das classes concretas de um determinado provedor.

Se você não sabe, a partir da ADO .NET 2.0, temos que as interfaces citadas acima são implementadas via Bases Classes que passam a ser herdadas pelos objetos concretos (SqlCommand, SqlConnection, etc.) e ai são implementados os métodos conforme o provedor específico.

A seguir temos um tabela mostrando a estrutura das classes de acesso a dados da ADO .NET 2.0:

Interface Base Class Classe Concreta *
IDbConnection DbConnection SqlConnection
IDbCommand DbCommand SqlCommand
IDataReader/IDataRecord DbDataReader SqlDataReader
IDbTransaction DbTransaction SqlTransaction
IDbDataParameter DbParameter SqlParameter
IDataParameterCollection DbParameterCollection SqlParameterCollection
IDbDataAdapter DbDataAdapter SqlDataAdapter
  DbCommandBuilder SqlCommandBuilder
  DbConnectionStringBuilder SqlConnectionStringBuilder
  DBDataPermission SqlPermission

Vejamos então de forma bem resumida cada uma dessas interfaces.

IDbConnection

Representa uma conexão aberta com uma fonte de dados e é implementada pelos provedores de dados do .NET Framework que acessam bancos de dados relacionais.

Assim para se comunicar com um banco de dados você precisa de uma conexão de um provedor. Uma aplicação pode usar várias conexões para qualquer número de bancos de dados. Qualquer número de Comandos pode usar a mesma Conexão, mas apenas um Comando pode estar Executando em uma conexão particular de cada vez (note que isso inclui quando um DataReader está aberto em uma Conexão).

Instanciar a conexão é a única vez que você realmente precisa saber qual Provedor está usando e qual classe concreta usar. Depois disso, é podemos usar as Interfaces no resto do código.

Ao invés de usar :

   System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection ( ... )

Prefira usar:

  System.Data.IDbConnection con = new System.Data.SqlClient.SqlConnection ( ... )

E o método que usa a conexão como um parâmetro:

public int SeuMetodo ( System.Data.IDbConnection con ) { ... }         

IDbConnection

Representa uma instrução SQL executada enquanto está conectada a uma fonte de dados e é implementada pelos provedores de dados do .NET Framework que acessam bancos de dados relacionais.

Como instanciar um comando sem saber o tipo concreto real a ser usado ?

Você deixa a conexão fazer esse trabalho para você e conhecer qual tipo usar.

A interface IDbConnection possui um método chamado CreateCommand que instancia e retorna um comando do tipo correto. Você pode definir o CommandText e outras propriedades conforme necessário.

Assim você deve usar:

   System.Data.IDbCommand cmd = con.CreateCommand()

E também:

   public int SeuMetodo ( System.Data.IDbCommand cmd ) { ... }

Essa interface possui 3 métodos Execute :

  1. ExecuteScalar - Executa a consulta e retorna um único valor.(uma linha e uma coluna)
  2. ExecuteNonQuery - Executa a consulta e não retorna nenhuma coleção. Usado para instruções INSERT, DELETE e UPDATE onde retorna o número de registros afetados.
  3. ExecuteReader - Executa a consulta e retorna um objeto SqlDataReader;

Uma aplicação pode executar qualquer um desses métodos em um comando sem saber qual tipo específico de banco de dados está em uso.

IDataReader

Fornece um meio de ler um ou mais fluxos somente de encaminhamento de conjuntos de resultados obtidos pela execução de um comando em uma fonte de dados e é implementado pelos provedores de dados do .NET Framework que acessam bancos de dados relacionais.

Lembra do ExecuteReader ? Pois ele retorna um instância de IDataReader.

Então use:

  System.Data.IDataReader rdr = cmd.ExecuteReader()

e também:

  public int SeuMetodo ( System.Data.IDataReader rdr ) { ... }

Além disso, um IDataReader implementa IDataRecord, portanto considere usar este recurso quando precisar executar alguma operação em um resultado de um DataReader :


  public int DoSomething ( System.Data.IDataRecord rec ) { ... }

IDataParameter

Representa um parâmetro para um objeto Command e, opcionalmente, seu mapeamento para as colunas DataSet; e é implementado pelos provedores de dados do .NET Framework que acessam as fontes de dados.

Nota:  Não confunda o IDataParameter com IDbDataParameter

Assim como uma conexão pode instanciar um comando para você, um comando pode instanciar um parâmetro para você:


   System.Data.IDataParameter prm = cmd.CreateParameter()

A seguir, você pode definir o ParameterName e Value e adicionar o parâmetro para a ParameterCollection do comando.

O membro  'AddWithValue' é muito útil, e pertence a algumas classes que implementam a interface IDataParameterCollection, como SqlParameterCollection e OleDbParameterCollection, mas ele não é um membro da interface IDataParameterCollection, logo, você não pode confiar na sua presença se desejar ter uma  independência do provedor.

Lembre-se que o Provedor vai inferir o DbType quando o valor for definido de qualquer maneira e assim você não precisa definir o DbType.

IDataParameterCollection

Coleta todos os parâmetros relevantes para um objeto Command e seus mapeamentos para colunas DataSet e é implementado pelos provedores de dados do .NET Framework que acessam as fontes de dados.

Um comando tem uma propriedade Parameters que dá acesso a um IDataParameterCollection.

Mas como essas interfaces foram criadas antes da versão 2.0 do framework, não há genéricos. Um efeito colateral disso é que esta coleção trata seus membros como objetos em vez de IDataParameters. A conseqüência disso é que quando você acessa um parâmetro na coleção, você tem que dar um cast.

Isso não afeta muito a eficiência, mas é um problema na montagem se você tiver que fazer isso com frequência.

IDisposable

Fornece um mecanismo para liberar os recursos não gerenciados.

Procure sempre usar a instrução Using no seu código pois ela é usada para facilitar a implementação de executar código para liberá-lo em seguida.

  using (IDbConnection conn = new SqlConnection(connString))
  {
       // código
  }

Muitos exemplos da MSDN são exibidos sem usar esse recurso o que é uma falha da Microsoft pois esta incentivando a não utilização de um recurso que ela mesmo recomenda.

E estamos conversados...

"Grandes são as obras do Senhor, procuradas por todos os que nelas tomam prazer."
Salmos 111:2
Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti