Hoje o Visual Studio possui um wizard para que possamos conectar ao Banco de Dados, selecionar qual objeto do Banco vamos utilizar, e já criar um form para este objeto, gerando sozinho todos os comandos de Insert, Update e Delete para o TableAdapter.

O problema é que, ao fazer isto nossa aplicação fica amarrada a aquele Banco de Dados, e toda modificação em nossa tabela, deveremos atualizar o DataSet Tipado que foi gerado, para que possa ser atualizado os comandos.

Como deixar nossa aplicação mais flexível para acesso a Banco de Dados distintos e não tendo a preocupação de toda vez que modificar a tabela seja necessário atualizar o DataSet Tipado?

Hoje podemos contar com o CommandBuilder. Esta classe possui em todos os providers de Banco de Dados para  Dot.net, no nosso exemplo vamos usar o do SQL Server.

Então teremos um classe estática onde será implementado a geração dos códigos, como pode ser visto na Listagem 1.

Listagem 1: Classe que será responsável para geração dos comandos.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient; // Pois o nosso exemplo é para SQL Server
namespace CommandBuilder
{
    public static class  AcessoDados
    {
    }
}

Nesta classe teremos um método que receberá como parâmetro a consulta de select a ser executada. Estamos partindo do pressuposto que a aplicação já está conectada, nossa classe ficará como é mostrado na Listagem 2.

Listagem 2: Implementação do Método Gerar Comandos

public static class  AcessoDados
    {
        //Pressupomos que a parte de conexão com o Banco já está feita
        static SqlConnection conexao = new SqlConnection();
 
        public static SqlDataAdapter GerarComandos(string consulta)
        {
            SqlDataAdapter adapter = new SqlDataAdapter(consulta,conexao);
            SqlCommandBuilder comand = new SqlCommandBuilder(adapter);
            return adapter;
        }
    }

Este método receberá nossa consulta select da tabela que queremos carregar o comando (Ex: Select * from Produtos), instanciará um DataAdapter e através do deste irá gerar os comandos de Insert, Update, Delete de acordo com a Tabela passada e já setar os comandos no nosso DataAdapter, retornando o mesmo carregado com estas informações.

Para poder verificar os comandos que foram gerados, é necessário usar os métodos que podem ser visualizados na Listagem 3. 

Listagem 3: Comandos gerados através do CommandBuilder

comand.GetDeleteCommand();
/*DELETE FROM [PRODUTO] WHERE (([CODIGO] = @p1) AND
((@p2 = 1 AND [DESCRICAO] IS NULL) OR ([DESCRICAO] = @p3)) AND
((@p4 = 1 AND [DATA] IS NULL) OR ([DATA] = @p5)))*/
comand.GetInsertCommand();
//INSERT INTO [PRODUTO] ([DESCRICAO], [DATA]) VALUES (@p1, @p2)
comand.GetUpdateCommand();
/*UPDATE [PRODUTO] SET [DESCRICAO] = @p1, [DATA] = @p2
WHERE (([CODIGO] = @p3) AND ((@p4 = 1 AND [DESCRICAO] IS NULL) OR
([DESCRICAO] = @p5)) AND ((@p6 = 1 AND [DATA] IS NULL)
OR ([DATA] = @p7)))*/

Com nosso comandos gerados, a nossa gravação poderá ser usando o DataAdapter.Update(DataSet), pois com o método GerarComando nos DataApadater já´estará carregado com os comandos acima, justamente o que o Wizardo do Visual Studio iria fazer.

Conclusão

Com o CommandBuilder, conseguimos gerar os comandos de Inser,Delete e Update para a tabela que iremos trabalhar, permitidindo que façamos uma aplicação fexível ao banco de dados e alterações na estrutura do mesmo.

Lembrando que o CommandBuiderl não consegue gerar comandos caso haja join no comando de Select, ou seja, somente utilizar quando for gerar  os códigos para uma única tabela.