ADO .NET - Camada de Acesso a dados Genérica 1 (revisitado)


Hoje eu vou voltar a falar sobre o modelo Factory genérico disponível a partir da versão 2.0 da ADO .NET.

A partir da ADO.NET 2.0 a Microsoft facilitou muito o desenvolvimento de aplicações que usam banco de dados para serem multiplataforma.

Hoje você pode estar desenvolvendo para um servidor SQL Server, amanhã para um Oracle e quem depois para um MySQL. Não importa qual a sua fonte de dados. A ADO .NET permite e oferece uma plataforma agnóstica sobre a qual você pode criar aplicações de forma a que você escreve o seu código uma única vez e ele vai trabalhar com qualquer fonte de dados.

O modelo Factory genérico é uma arquitetura que permite o acesso a qualquer banco de dados, a partir de um conjunto de código.

No namespace System.Data.Common existem algumas novas classes que nos permitem criar código independente de plataforma muito facilmente e neste artigo eu vou mostrar como usar esses recursos para criar uma singela camada de acesso a dados genérica de forma que poderemos acessar qualquer banco de dados para o qual exista um provedor disponível para a plataforma .NET.

Para detalhes da teoria sugiro que você leia os artigos:

Recursos usados:

Criando uma camada de acesso a dados genérica

Vamos criar um novo projeto no Visual Studio 2012 Express for desktop clicando em New Project;

A seguir selecione o template Visual Basic -> Windows Forms Application e informe :

Teremos assim uma solução contendo um projeto Windows Forms que iremos usar apenas para testar a nossa camada de acesso a dados genérica.

Vamos então incluir um novo projeto do tipo Class Library na solução onde iremos criar duas classes que serão a nossa camada de acesso a dados genérica.

No menu FILE clique em Add -> New Project;

A seguir selecione Visual Basic -> Class Library e informe o nome DALGeneric e clique em OK;

Teremos assim 1 solução com dois projetos :

Vamos então abrir o projeto DALGeneric e renomear a classe Class1.vb para ConexaoDB.vb e a seguir insira o código abaixo nesta classe:

Imports System.Configuration

Public Class ConexaoDB

    Shared _connectionString As String
    Shared _providerName As String

    Shared Sub New()
        Try
            _connectionString = ConfigurationManager.ConnectionStrings("ConexaoBD").ConnectionString
            _providerName = ConfigurationManager.ConnectionStrings("ConexaoBD").ProviderName
        Catch ex As Exception
            Throw New Exception("Erro ao acessar a string de conexão")
        End Try

    End Sub

    Public Shared Function ConnectionString() As String
        Return _connectionString
    End Function

    Public Shared Function ProviderName() As String
        Return _providerName
    End Function

End Class

Esta classe possui um construtor onde estamos obtendo a string de conexão e o nome do provedor a partir do arquivo de configuração App.Config.

Para isso temos que incluir uma referência no projeto ao namespace System.Configuration.

Clique no menu PROJECT -> Add Reference. Selecione a guia Assemblies e marque System.Configuration clicando a seguir em OK;

Definimos dois métodos estáticos (shared) :

Vamos agora criar outra classe no projeto DALGeneric selecionando o menu PROJECT->Add Class e informando o nome AcessoGenericoDB.vb;

Vamos começar definindo os seguintes namespaces nesta classe:

Imports System.Data
Imports System.Data.Common
Imports System.Collections.Generic

Observe que não estamos usando um namespace especifico para um provedor de banco de dados mas estamos usando o namespace System.Data.Common.

A ADO.NET  introduziu o recurso de Factories  onde a matéria prima da Factory são os provedores que queremos usar, e os produtos são os classes independente dos provedores que precisamos usar.

As classes de provedor independentes incluem DbConnection, DbCommand e DbParameter, bem como um série de outras classes. A maneira como elas são usadas, é muito semelhante à forma como elas foram usados no antigo modelo, mas elas vêm de uma Factory e você não tem que escrever nenhum código para obtê-las.

Em outras palavras você não tem mais que codificar qualquer instrução select/case/switch e melhor ainda, a plataforma .NET irá fazer todo o trabalho para você. Assim, por exemplo se você desejar trabalhar como objeto connection SqlConnection tudo o que você precisa fazer é o seguinte:

Public Shared Function GetConnection(ByVal providerName As String)
      Return System.Data.Common.DbProviderFactories.GetFactory(providerName).CreateConnection()
End Function
public static object GetConnection(string providerName)
{
return System.Data.Common.DbProviderFactories.GetFactory(providerName).CreateConnection();
}

Se você quer usar um objeto Command é tão simples como chamar CreateCommand() na Factory retornada por GetFactory().

Este código é muito mais limpo e fácil de manter. Você nunca terá que modificá-lo, até mesmo para usar provedores.

Seguindo esta abordagem vamos criar 3 métodos na classe AcessoGenericoDB :

  1. CriarComando
  2. ExecutarComando
  3. CriarParametro

Nosso objetivo é realizar o acesso e a manutenção em qualquer banco de dados relacional implementando as funcionalidades que permitem incluir, editar e excluir dados.

Para poder executar essas operações vamos definir uma enumeração nesta classe na qual vamos definir os principais tipos de comandos que são usados contra um banco de dados. Vemos abaixo a enumeração TIpoDeComando que define as principais operações básicas que serão necessárias para realizar o nosso objetivo.

 Public Enum TipoDeComando
        ExecuteNonQuery
        ExecuteReader
        ExecuteScalar
        ExecuteDataTable
        ExecuteDataSet
    End Enum

1- Método CriarComando

Public Shared Function CriarComando(comandoTexto As String, comandoTipo As CommandType, listaParametros
As List(Of DbParameter))  As DbCommand

        Try
            Dim oFactory = DbProviderFactories.GetFactory(ConexaoDB.ProviderName)
            Dim oConn = oFactory.CreateConnection

            oConn.ConnectionString = ConexaoDB.ConnectionString

            Dim oCmd = oConn.CreateCommand

            oCmd.CommandText = comandoTexto
            oCmd.CommandType = comandoTipo

            If Not IsNothing(listaParametros) Then
                For Each oParam In listaParametros
                    oCmd.Parameters.Add(oParam)
                Next
            End If

            Return oCmd

        Catch ex As Exception
            Throw ex
        End Try

    End Function

 

O método CriarComando tem como objetivo criar um comando para um provedor. Observe que estamos usando a classe DBProviderFactories.

O novo modelo de provedor ADO.NET esta baseado em um série de classes base no namespace System.Data.Comom. A classe DBProviderFactories permite a realização de dois tipos de tarefas:

  1. Obter uma lista de todos os provedores existentes via método estático GetFactoryClasses;
  2. Criar uma instância de um determinado Factory conforme o seu tipo via método GetFactoryClass

Uma classe base de provedor é um objeto factory que é usado para criar um conjunto de objetos relacionados como SqlConnection e SqlCommand. Eles retornam um tipo de classe abstrata do tipo DBConnection. As classes de provider factory são derivadas de uma classe base abstrata : System.Data.Common.DbProviderFactory , e , para cada tipo de base de dados a ser acessado temos uma nova classe derivada desta classe base abstrata. A classe DbDataProvider define o número de funções  que esta subclasse precisa implementar:

CreateComand()

Cria um objeto Command derivado de DBCommand.

CreateCommandBuilder()

Cria um objeto derivado de DbCommandBuilder

CreateConnection()

Cria um objeto derivado de DbConnection.

CreateConnectionStringBuilder()

Cria um objeto derivado de DbConnectionStringBuilder

CreateDataAdapter()

Cria um objeto derivado de DbDataAdapter.

CreateDataSourceEnumerator()

Cria um objeto derivado de DbDataSourceEnumerator.

CreateParameter()

Cria um objeto derivado de DbParameter.

CreatePermission()

Cria um objeto derivado de CodeAccessPermission,

Funções DbDataProvider

Desde que o DbProviderFactory apropriado  foi criado a função na tabela acima pode ser usada para criar o objeto apropriado ao invés de usar o operador New como anteriormente.(Para determinar todas as classes DbProviderFactory disponíveis e criar suas classes adicionais é fornecido a classe System.Data.Common.DbProviderFactories)

Cada provedor de dados faz o registro de uma classe ProviderFactory no arquivo machine.config da plataforma .NET. A classe base DbProviderFactory e a classe ProviderFactories podem retornar um DataTable de informações sobre os diferentes provedores registrados no arquivo machine.config e podem recuperar a ProviderFactory conforme a sequência do provedor fornecida ou um DataRow de um DataTable.

O método CriarComando foi definido para receber os seguintes parâmetros:

Assim temos a sequência de operações que serão executadas:

2 - Método ExecutarComando

 Public Shared Function ExecutarComando(comandoTexto As String, comandoTipo As CommandType, listaParametros
As List(Of DbParameter), tipoComando As TipoDeComando) As Object

        Dim command = CriarComando(comandoTexto, comandoTipo, listaParametros)
        Dim retorno As Object = Nothing

        Try
            command.Connection.Open()

            Select Case tipoComando
                Case TipoDeComando.ExecuteNonQuery
                    retorno = command.ExecuteNonQuery
                Case TipoDeComando.ExecuteReader
                    retorno = command.ExecuteReader
                Case TipoDeComando.ExecuteScalar
                    retorno = command.ExecuteScalar
                Case TipoDeComando.ExecuteDataTable
                    Dim table = New DataTable
                    Dim reader = command.ExecuteReader
                    table.Load(reader)
                    reader.Close()
                    retorno = table
                Case TipoDeComando.ExecuteDataSet
                    Dim oFactory = DbProviderFactories.GetFactory(ConexaoDB.ProviderName)
                    Dim da As DbDataAdapter = oFactory.CreateDataAdapter
                    command.CommandText = comandoTexto
                    command.CommandType = comandoTipo
                    da.SelectCommand = command
                    Dim ds As New DataSet
                    da.Fill(ds)
                    retorno = ds
            End Select
        Catch ex As Exception
            Throw ex
        Finally
            If Not tipoComando = TipoDeComando.ExecuteReader Then
                If command.Connection.State = ConnectionState.Open Then
                    command.Connection.Close()
                End If
                command.Connection.Dispose()
            End If
        End Try
        Return retorno
    End Function

 

O método ExecutarComando foi definido para receber os seguintes parâmetros:

Estamos verificando o tipo de comando e executando a operação correspondente com o comando que foi criado.

Para os tipos de comando ExecuteDataTable e ExecuteDataSet estamos retornando respectivamente um datatable e um dataset que criamos via código.

3 - Método CriarParametros

Public Shared Function CriarParametro(nomeParametro As String, tipoParametro As DbType, valorParametro As Object) As DbParameter

        Try
            Dim oFactory = DbProviderFactories.GetFactory(ConexaoDB.ProviderName)

            Dim oParam = oFactory.CreateParameter()

            If Not IsNothing(oParam) Then
                oParam.ParameterName = nomeParametro
                oParam.DbType = tipoParametro
                oParam.Value = valorParametro
            End If

            Return oParam

        Catch ex As Exception
            Throw ex
        End Try
    End Function

Este código define a criação de parâmetros para utilização com os comandos criados quando necessário.

Poderíamos ter implementado mais funcionalidades na nossa camada de acesso a dados mas vamos devagar e sempre. Com o que fizemos até agora já podemos realizar as operações para incluir, selecionar , deletar e editar registros.

Aguarde a segunda parte do artigo quando iremos testar a nossa camada de acesso a dados genérica com dois bancos de dados distintos: SQL Server e MySQL :  ADO .NET - Camada de Acesso a dados Genérica 2 (revisitado)

Veja os Destaques e novidades do SUPER DVD Visual Basic 2013 (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Mar 1:1 Princípio do evangelho de Jesus Cristo, Filho de Deus.

Mar 1:2 Conforme está escrito no profeta Isaías: Eis que envio ante a tua face o meu mensageiro, que há de preparar o teu caminho;

Mar 1:3 voz do que clama no deserto: Preparai o caminho do Senhor, endireitai as suas veredas;

Mar 1:4 assim apareceu João, o Batista, no deserto, pregando o batismo de arrependimento para remissão dos pecados.

        Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti