Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RSS iMasters

[Resolvido] C# - Usando código independente do banco de dados

Recommended Posts

Imagine a situação: você precisa escrever o seu código de acesso aos dados de forma que ele possa ser configurado para trabalhar com qualquer banco de dados relacional suportado por um provedor ADO .NET. Como você vai fazer isso?

Bom, a primeira coisa a se fazer é saber se realmente você precisa desse recurso. Caso contrário, você vai trabalhar em vão. Portanto, pense bem antes de iniciar a tarefa, visto que não é todo o dia que uma empresa decide trocar o seu banco de dados. Em geral, a troca de um banco de dados afeta a empresa como um todo e por isso somente em casos muito extremos elas tomam a decisão de fazer a troca do fornecedor.

Mas vamos supor que você quer que o seu código funcione com os principais RDBMS suportados pelos provedores ADO .NET. Estou falando do SQL Server, MySQL, Oracle, MSAccess etc. Se você não tem a mínima ideia de como fazer essa tarefa, este artigo vai lhe mostrar o caminho.

 

É preciso programar usando as interfaces dos provedores de dados ADO .NET, em vez de usar suas classes concretas. Só assim você não vai depender dos recursos e dos tipos de dados que são específicos para cada implementação. Utilize também as fábricas de classes e os métodos para instanciar os objetos dos provedores de dados que você pretende utilizar.

Uma das regras de ouro da orientação a objetos é: "programe para uma interface e não para uma implementação". E, se você não entendeu até hoje o que isso significa, quem sabe hoje, usando o enfoque deste artigo, tudo isso fique mais claro para você.

Quando você usa uma implementação específica para um provedor de dados, como, por exemplo, o provedor de dados SQL Server, isso pode simplificar o seu código, o que pode ser adequado se você precisar dar suporte para apenas um tipo de banco de dados ou acessar os recursos específicos fornecidos por esse provedor.

Esse caminho, no entanto, fará com que você tenha que reescrever e testar o seu código novamente, se você quiser usar um provedor de dados diferente. Você terá que reescrever toda a sua camada de acesso aos dados - isso se você adotou uma arquitetura em camada separando as responsabilidades. Se você não fez isso, o trabalho será muito maior!

E quais são essas interfaces que você precisa conhecer?

Abaixo temos resumo das principais interfaces que você deve programar quando for escrever o seu código genérico para trabalhar com qualquer provedor de dados ADO .NET:

Interface Descrição
IDbConnection Representa uma conexão com um banco de dados relacional. Você deve programar a lógica para criar um objeto de conexão do

tipo apropriado com base nas informações de configuração de seu aplicativo, ou usar o método factory DbProviderFactory.CreateConnection.

IDbCommand Representa um comando SQL que é emitido para um banco de dadaos relacional. Você pode criar objetos IDbCommand do tipo apropriado

usando o IDbConnection.CreateCommand ou o método factory DbProviderFactory.CreateCommand.

IDataParameter Representa um parâmetro para um objeto IDbCommand. Você pode criar objetos IDataParameter do tipo correto usando o IDbCommand.Parameters.Add IDbCommand.CreateParameter, ou o método factory DbProviderFactory.CreateParameter.
IDataReader Representa o conjunto de resultados de uma consulta de banco de dados e fornece acesso para as linhas e colunas. Um objeto do tipo correto será devolvido quando você chamar o método IDbCommand.ExecuteReader.
IDbDataAdapter Representa o conjunto de comandos utilizados para preencher uma System.Data.DataSet a partir de um banco de dados relacional e atualizar o

banco de dados com base nas alterações do DataSet. Você deve programar a lógica para criar um objeto adaptador de dados do tipo apropriado

com base em informações de configuração de seu aplicativo ou usar o método DbProviderFactory.CreateAdapter.

A classe System.Data.Common.DbProviderFactory fornece um conjunto de métodos de fábrica para a criação de todos os tipos de objetos de provedor de dados, tornando-a muito útil para a implementação de código de banco de dados genéricos.

A mais importante delas é a classe DbProviderFactory, que fornece um mecanismo para a obtenção de uma instância IDbConnection inicial, que é o ponto de partida crítico para escrever código ADO.NET genéricos.

Cada implementação de provedor de dados padrão (exceto o SQL Server CE) inclui uma única classe factory derivada de DbProviderFactory.

A seguir, temos uma relação das subclasses de DbProviderFactory:

  • System.Data.Odbc.OdbcFactory;
  • System.Data.OleDb.OleDbFactory;
  • System.Data.OracleClient.OracleClientFactory;
  • System.Data.SqlClient.SqlClientFactory.

Você pode obter uma instância da subclasse DbProviderFactory apropriada usando a classe DbProviderFactories, que é, efetivamente, uma fábrica de fábricas. Cada fábrica de provedor de dados é descrita por informações de configuração no arquivo machine.config.

Abaixo temos um exemplo para o data adatpter SQL Server. (Isso pode ser alterado ou substituído, se necessário, por informações de configurações específicas de aplicações).

<configuration>

<system.data>

<DbProviderFactories>

<add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

<add name="Odbc Data Provider" ... />

<add name="OleDb Data Provider" ... />

<add name="OracleClient Data Provider" ... />

<add name="SQL Server CE Data ... />

</DbProviderFactories>

</system.data>

</configuration>

Você pode enumerar as fábricas de provedores de dados disponíveis chamando DbProviderFactories.GetFactoryClasses, que retorna uma System.Data.DataTable contendo as seguintes colunas:

  • Name - Contém um nome legível para o provedor;
  • Description - Contém uma descrição para o provedor;
  • InvariantName - Contém o nome único usado para se referir ao provedor de dados;
  • AssemblyQualifiedName - Contém o nome qualificado da classe DbProviderFactory para o provedor de dados;

Normalmente, você permitiria que o provedor fosse selecionado no momento da instalação ou na primeira vez em que a aplicação fosse executada e, em seguida, armazenaria as configurações como usuário ou como dados de configuração de aplicativo. A peça mais importante da informação é o InvariantName, que você passa para o método DbProviderFactories.GetFactory para obter a implementação DbProviderFactory, que você vai usar para criar suas instâncias de IDbConnection.

Vejamos, a seguir, um exemplo prático que procura ilustrar como usar toda essa teoria.

Exemplo prático

Neste exemplo, vamos demonstrar a enumeração de todos os provedores de dados configurados para a máquina local e a máquina de aplicação.

Ele utiliza a classe DbProviderFactories para instanciar um objeto DbProviderFactory. E é a partir desse objeto (na verdade, um SqlClientFactory) que ele cria o IDbConnection apropriado. Em seguida, usamos os métodos de fábrica das interfaces de provedor de dados para criar outros objetos necessários, resultando em um código genérico.

Abra o Visual C# 2010 Express Edition e crie um novo projeto, do tipo Windows Forms Application, com o nome DbProviderFactory_Exemplo. A seguir, no formulário form1.cs, inclua dois controles Buttons e dois controles ListBox, conforme o leiaute abaixo:

46745.gif

Vamos iniciar declarando os namespaces usados:

  • using System;

  • using System.Data;

  • using System.Windows.Forms;

  • using System.Data.Common.

A seguir, vamos definir o código do evento Click do botão de comando para obter a lista de provedores instalados, conforme mostrado abaixo:

private void btnProvedores_Click(object sender, System.EventArgs e)

{

// Obtêm a lista de provedores de dados ADO.NET registros na máquina e no arquivo de configuração

using (DataTable providers = DbProviderFactories.GetFactoryClasses())

{

// Enumera o conjunto de provedoers de dados e exibe os detalhes

lstProvedores.Items.Add("ADO.NET Data Providers Disponíveis :");

lstProvedores.Items.Add(" ");

foreach (DataRow prov in providers.Rows)

{

lstProvedores.Items.Add(" Nome: " + prov["Name"]);

lstProvedores.Items.Add(" Descrição: " + prov["Description"]);

lstProvedores.Items.Add(" Nome Invariant " + prov["InvariantName"]);

lstProvedores.Items.Add("");

}

}

}

Executando o projeto e clicando neste botão iremos obter:

46747.gif

Obs: Estes são os provedores instalados na minha máquina. A sua lista pode ser diferente.

Agora, vamos definir o código do evento Click, do botão de comando que mostra o exemplo de acesso ao SQL Server:

private void btnAcessoDados_Click(object sender, System.EventArgs e)

{

// Obtêm o DbProviderFactory para o SQL Server, o provedor a usar

// poderia ser selecionado pelo usuário ou lido a partir de um arquivo de configuração

// Neste caso nos simplesmente pssariamos o nome invariant

DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");

 

// Usa o DbProviderFactory para criar o IDbConnection inicial e

// então os métodos factory dos provedores de dados para os demais objetos

using (IDbConnection con = factory.CreateConnection())

{

// Normalmente le a string de conexão de um local seguro

// Neste exemplo usamos um valor padrão

con.ConnectionString = @"Data Source = .\sqlexpress;" + "Database = Northwind; Integrated Security=SSPI";

 

// Cria e configura um novo comando

using (IDbCommand com = con.CreateCommand())

{

com.CommandType = CommandType.StoredProcedure;

com.CommandText = "Ten Most Expensive Products";

// Abre a conexão

con.Open();

// Executa o comando e processa o resultado

using (IDataReader reader = com.ExecuteReader())

{

lstDados.Items.Add(Environment.NewLine);

lstDados.Items.Add("Preço dos 10 Produtos mais caros.");

lstDados.Items.Add(Environment.NewLine);

while (reader.Read())

{

// Exibe os detalhes dos produtos

lstDados.Items.Add(" " + reader["TenMostExpensiveProducts"] + "\t\t" + reader["UnitPrice"]);

}

}

}

}

No exemplo, estamos acessando a consulta armazenada Ten Most Expensive Products do banco de dados Northwind.mdf. O resultado obtido para esse código é visto a seguir:

46749.gif

O exemplo usado foi especifico para o SQL Server, mas em um código genérico você poderia fazer assim:

1. Definir os provedores que deseja usar e que estejam disponíveis no arquivo de configuração da aplicação:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<appSettings>

<add key="sqlProvider" value="System.Data.SqlClient" />

<add key="oledbProvider" value="System.Data.Oledb" />

<add key="MySqlProvider" value="System.Data.MySqlClient" />

<add key="OdbcProvider" value="System.Data.Odbc" />

</appSettings>

</configuration>

2. Ler o provedor de dados específico e obter o seu nome invariante; criar o DbProviderFactory; criar a string de conexão e montar a string de conexão conforme o provedor:

 string sInvariant = ConfigurationManager.AppSettings["oledbProvider"];

DbProviderFactory df = DbProviderFactories.GetFactory(sInvariant);

 

DbConnectionStringBuilder csb = df.CreateConnectionStringBuilder();

string paramName = string.Empty;

 

switch (sInvariant) {

case "System.Data.SqlClient":

csb.Add("Data Source", "localhost");

csb.Add("Initial Catalog", "Northwind");

csb.Add("Integrated Security", "SSPI");

paramName = "@nomeparametro";

break;

case "System.Data.OleDb":

csb.Add("Provider", "SQLOLEDB");

csb.Add("Data Source", "localhost");

csb.Add("Initial Catalog", "Northwind");

csb.Add("Integrated Security", "SSPI");

paramName = "?";

break;

case "System.Data.Odbc":

csb.Add("Driver", "{SQL Server}");

csb.Add("Server", "localhost");

csb.Add("Database", "Northwind");

csb.Add("Trusted_Connection", "yes");

paramName = "?";

break;

default:

return;

break;

}

Esta é apenas uma indicação de como fazer, mas existem outras maneiras de se obter o mesmo resultado.

Aguarde que em outro artigo irei criar um exemplo completo sobre este assunto usando a linguagem C#.

Pegue o projeto completo aqui: DbProviderFactory_Exemplo.zip

 

http://imasters.com.br/artigo/24332/banco-de-dados/c-usando-codigo-independente-do-banco-de-dados

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.