VB.NET  - Usando CommandBuilder para gerar comandos SQL


A classe CommandBuilder faz parte do .NET Framework e tem como objetivo construir automaticamente comandos SQL Insert, Update e Delete para uma DataTable baseado em instruções SQL. Ele dá uma mãozinha ao desenvolvedor e ajuda o código ficar mais limpo e fácil de entender evitando que os comandos SQL fiquem ali embutidos. Para cada provedor existe uma classe CommandBuilder.

Como neste artigo vou acessar um banco de dados SQL Server a classe que vou tratar e usar será a classe SqlCommandBuilder.

Se você der uma espiada na MSDN vai encontrar a seguinte definição para esta classe:

"Gera automaticamente comandos para tabela simples usados para conciliar as alterações feitas em um DataSet associado a um banco de dados SQL Server. Esta classe não pode ser herdada."

O objeto SqlDataAdapter não gera automaticamente comandos Transact-SQL necessários para ajustar as alterações feitas a um DataSet associado com uma instância do SQL Server. Você pode , no entanto, criar um objeto SqlCommandBuilder para gerar automaticamente estes comandos para atualizações em uma tabela única definindo a propriedade SelectCommand do SqlDataAdapter. Assim , qualquer comando SQL que você não defina será gerado pela classe SqlCommandBuilder.  A classe SqlCommandBuilder registra um escutador para o evento RowUpdating sempre que você define a propriedade DataAdapter.

Para gerar comandos Insert , Update e Delete , esta classe usa a propriedade SelectCommand para retornar um conjunto requerido de metadados automaticamente.  Se você mudar a propriedade SelectCommand depois que o metadado tiver sido retornado você poderá chamar o método RefreshSchema para atualizar os metadados.

A classe SqlCommandBuilder também usa as propriedades  Connection, CommandTimeOut e Transaction referenciadas por SelectCommand. Você pode chamar RefreshSchema se qualquer uma destas propriedades for modificada ou se o próprio SelectCommand tiver sido substituído.

Se você chamar o método Dispose , o SqlCommandBuilder será desassociado do SqlDataAdapater e os comandos gerados não serão mais usados.

No nosso exemplo , primeiro eu vou preencher um datagrid com os dados da tabela Products do banco de dados Northwind do SQl Server e depois eu vou usar o CommandBuilder para poder atualizar os dados.

Crie então no VS.NET um projeto do tipo Windows Application usando a linguagem VB.NET . A seguir defina o import da classe SqlClient:

Imports System.Data.SqlClient

E defina as variáveis para o comando SQL e a conexão bem como defina o dataset que será usado no projeto:

Private Const strSQL As String = "SELECT ProductID, ProductName, QuantityPerUnit,UnitPrice FROM Products ORDER BY ProductID"
Private Const conexaoSQL As String = "server=(local);trusted_connection=true;database=Northwind;Integrated Security=SSPI
"

' define o dataset
Private ds As DataSet

No evento Load do formulário padrão - form1.vb -  inclua o seguinte código:

' carrega o datagrid com dados 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim da As SqlDataAdapter
        ' Cria o objeto SqlDataAdapter.
        da = New SqlDataAdapter(strSQL, conexaoSQL)

        ' Mapeia a tabela para Products.
        da.TableMappings.Add("Table", "Products")

        ' preenche o dataset
        ds = New DataSet
        Try
            da.Fill(ds)
        Catch ex As Exception
            MsgBox(ex.Message())
        End Try
        ' vincula o datagrid a tabela produtos
        dg.SetDataBinding(ds, "Products")
    End Sub

 

Este código apenas acessa a tabela Products do banco de dados Northwind do SQL Server e preenche o datagrid com os dados. Abaixo a tela obtida com os dados sendo exibidos:

Se tentarmos fazer uma alteração em uma linha do datagrid ao fecharmos a aplicação e abrirmos novamente iremos perceber que as alterações não foram feitas no banco de dados.

Vamos agora incluir o código no evento Closing do formulário que irá usar o SqlCOmmandBuilder para permitir a atualização do dataset e dos dados , permitindo assim que as alterações seja efetivamente gravadas.

Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

        ' se houve mudanças no dataset então ...
        If ds.HasChanges() Then
            Dim da As SqlDataAdapter
            Dim cmdb As SqlCommandBuilder
            ' Cria o DataAdapter
            da = New SqlDataAdapter(strSQL, conexaoSQL)
            ' Mapeia a tabela para Products.
            da.TableMappings.Add("Table", "Products")
            ' usa o CommandBuilder para gerar os comandos para 
            ' incluir , atualizar e excluir
            ' sem este comando a atualização vai falhar...
            cmdb = New SqlCommandBuilder(da)

            ' Salva as alterações
            da.Update(ds)
        End If

    End Sub

 

Acima temos o código que faz o seguinte :

-Verifica se houve alterações no dataset ( If ds.HasChanges() )

-Em caso positivo criamos um dataAdatper para conexão e usamos a classe SqlCommandBuilder.

-Finalmente atualizamos o dataset usando o comando update do dataAdapter.

Pronto , agora os dados foram gravados com sucesso. Você mesmo pode verificar isto abrindo novamente a aplicação.

Em um próximo artigo iremos analisar as entranhas do CommadBuilder.

Pegue o projeto aqui: sqlCommandBuilder.zip

Eu sei , é apenas VB.NET , mas eu gosto...


José Carlos Macoratti