ADO.NET - Usando Factories de Provedores


 Dentre as inúmeras novidades que a plataforma .NET trouxe na versão 2.0 com relação ao acesso a dados temos o novo conceito de provider e de factory contidos na classe Data.Comon.DbProviderFactories.

Até o momento quando pretendíamos efetuar uma conexão com uma base de dados criávamos os objetos diretamente. Assim, para acessar o SQL Server usávamos as classes SqlConnection, SqlDataAdapter, SqlXXX; para acessar uma base de dados Access usávamos os provedores OleDbConnection,OleDbDataAdapater , OleDbCommand, OleDbXXX; assim por diante;ou seja tínhamos uma série de classes específicas de provedores que eram usadas conforme a fonte de dados a ser acessada.

O problema é quando desejamos poder acessar tanto uma base SQL Server como uma base Oracle ou Access usando código genérico.

Isto era possível pois cada classe implementava uma interface genérica IDbConnection, IDbDataAdapter, IDbCommand, etc.

O novo modelo de provedor ADO.NET 2.0 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.

Com base nisto podemos descobrir quais os provedores de dados instalados usando o código abaixo:

Imports System.Data.common
 

Public Class Form1


Private
Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click


Dim factory As DbProviderFactory =
Nothing

Dim dtFactories As DataTable = DbProviderFactories.GetFactoryClasses()

Dim vetor As ArrayList = New ArrayList

Dim i As Integer = 0


For
Each drFactory As DataRow In dtFactories.Rows

  Try

     factory = DbProviderFactories.GetFactory(drFactory)

     vetor.Add(factory)

     ListBox1.Items.Add(vetor(i))

     i = i + 1

  Catch ex As Exception

     factory = Nothing

  End Try

Next

End Sub

End Class


Exibindo os provedores de dados instalados

No código acima DbProviderFactories.GetFactoryClasses() retorna um DataTabe com todos os possíveis provedores de dados.
Usamos DbProviderFactories.GetFactory  para criar um DbProviderFactory baseado no nome da DataRow do DataTable obtido acima.

Poderíamos usar o código abaixo para tentar efetuar a conexão com a base de dados MSDE. Como o provedor de dados é o Data.SqlClient haveria 3 tentativas frustradas com exibição de mensagem de erros pois a string de conexão usada refere-se ao provedor SqlClient que é o último data provider registrado no machine.config.

Imports System.Data.common
 

Public Class Form1


Private
Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click


Dim factory As DbProviderFactory =
Nothing

Dim conn As DbConnection = Nothing

Dim dtFactories As DataTable = DbProviderFactories.GetFactoryClasses()

Dim i As Integer = 0


For
Each drFactory As DataRow In dtFactories.Rows

Try

   factory = DbProviderFactories.GetFactory(drFactory)

   conn = factory.CreateConnection()

   conn.ConnectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind; _
   User ID=sa;password=;Data Source=MACORATI\VSDOTNET"

   conn.Open()

   conn.Close()

   conn = Nothing

    Exit For

Catch ex As Exception

   conn = Nothing

   factory = Nothing

   MsgBox(ex.Message)

End Try

Next

End Sub

End Class

Vamos mostrar um exemplo onde iremos trabalhar com classes de uma base de dados sem definirmos o tipo das classes. Vamos preencher um DataGridView com os dados da tabela Orders do banco de dados Northwind do MSDE (compatível com SQL Server).

Obs: Utilize uma string de conexão compatível com a sua base de dados.

Crie um novo projeto no Visual Basic 2005 Express com o nome de acessoBD, e, no formulário principal inclua um componente DataGridView(dgv1) e um botão de comando (btnPreencherGrid) conforme figura abaixo:

Defina o seguinte import no código :

Imports System.Data.Common

Agora clique duas vezes no botão de comando do formulário e inclua o seguinte código :

Private Sub btnPreencherGrid_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPreencherGrid.Click


Dim
provider As String =
"System.Data.SqlClient"


Dim
factory As
DbProviderFactory = DbProviderFactories.GetFactory(provider)

Dim cnn As DbConnection = factory.CreateConnection


cnn.ConnectionString =
"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind;User ID=sa;password=;Data Source=MACORATI\VSDOTNET"


Dim
cmd As
DbCommand = factory.CreateCommand


cmd.Connection = cnn

cmd.CommandText = "select * from Orders"

cmd.CommandType = CommandType.Text


cnn.Open()


Dim
reader As DbDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)

Dim info As DataTable = New DataTable


info.Load(reader)


reader.Close()


dgv1.DataSource = info

End Sub

Nota: Poderíamos ter armazenado a string de conexão e a  informação do provedor de dados no arquivo de configuração web.config:
 
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
   <add key="DbProvider" value="System.Data.SqlClient"/>
    <add key="ConnectionString" value="Server=localhost; Database=Northwind;Integrated Security=true;"/>
</appSettings>
</configuration>

Para obter os valores do web.config teríamos que usar o seguinte código:

Dim dbfactory As DbProviderFactory = DbProviderFactories.GetFactory(ConfigurationSettings.AppSettings.Get("DbProvider"))
dbconn.ConnectionString = ConfigurationSettings.AppSettings.Get("ConnectionString")

Este exemplo ilustra como você pode trabalhar com as classes de uma base de dados sem especificar o tipo das classes; perceba que embora eu esteja acessando uma base de dados MSDE (compatível com SQL Server) e que usa a classe SQLClient eu não precisei especificar nada a respeito desta classe.

As classes do tipo Factory são capazes de criar os objetos associados que permitem o acesso a base de dados. Foi necessário apenas definir o provedor na linha de código :

Dim provider As String = "System.Data.SqlClient"

A seguir, usando o método GetFactory, criamos um DbProviderFactory baseado no provedor fornecido acima.

Dim factory As DbProviderFactory = DbProviderFactories.GetFactory(provider)

Dim cnn As DbConnection = factory.CreateConnection

 

Observe que criamos um DataReader e preenchemos o um DataTable usando o método Load.

Dim info As DataTable = New DataTable

info.Load(reader)

 

Executando o projeto teremos o seguinte resultado:

 

 

Pegue o código do projeto aqui : acessoBD.zip

 

Até breve...

 

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 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti