ADO.NET 2.0 - RowState - Alterando o estado de uma linha


O objeto Data Adapter é parte integrante dos provedores gerenciados da ADO.NET , e são um conjunto de objetos usados para efetuar a comunicação entre a fonte de dados e o DataSet. Geralmente isto significa efetuar a leitura dos dados de um banco de dados e preencher um dataset, efetuar a manutenção de dados e em seguida escrever de volta no banco de dados com as informações atualizadas do dataset. Na verdade um data adapter pode mover dados entre qualquer fonte de dados e um dataset.

Geralmente os adapters são configuráveis , permitindo que você defina qual dados deseja mover para o dataset e a partir do dataset. Com frequência isto é realizado com a utilização de sentenças SQL ou procedimentos armazenados que são invocados para ler e escrever para a fonte de dados.

O Visual Studio torna disponíveis os seguintes Adapters:

Você pode criar e manipular Adapters usando os seguintes namespaces dos provedores gerenciados da .NET Framework

SqlClient Managed-Provider Namespace OleDb Managed-Provider Namespace

Em geral cada data adapter troca dados entre uma única tabela de dados fonte e um único objeto Datatable no DataSet. Se o dataset contém múltiplos data tables, a estratégia é ter múltiplos data Adapters alimentando os dados para cada um deles e escrevendo os dados de volta para cada tabela fonte individual.

Quando você desejar preencher uma tabela em um DataSet você chama um método adapter que executa uma instrução SQL ou uma stored procedure. O Adapter cria um objeto data reader (SqlDataReader, OleDbDataReader, OdbcDataReader, or OracleDataReader) para ler os dados para o dataset.

Nota:Você pode ler dados de um banco de dado sem ter que armazená-lo em um dataset, o que pode ser muito eficiente para situações que envolvem dados de somente leitura. Você pode também executar instruções SQL diretamente sem ter que usá-las para preencher um dataset.

Quando você usa o método Update do DataAdapter ele examina o RowState da linha para saber se ela deve ser atualizada, inserida ou eliminada. O mesmo ocorre quando você usa o método GetChanges.

Quando uma linha é modificada em um DataSet o RowState da linha pode assumir os seguintes valores: Modified, Added ou Unchanged.

Na versão anterior da ADO.NET estes valores não podiam ser configurados diretamente, mas na ADO.NET 2.0 podemos configurar diretamente o estado da linha através dos novos métodos :

  1. SetModified (Altera o estado da linha para Modified)
  2. SetAdded (altera o estado da linha para Added)

Nota: O valor de RowState depende de dois fatores: 1-) Do tipo de operação que foi realizado na linha e 2-) Se o método AcceptChanges foi chamado no DataRow.

E qual a vantagem disto ? (você pode estar se perguntando...)

Existem situações nas quais o novo recurso pode ser usado como por exemplo : copiar as linhas de uma tabela de um banco de dados para outra tabela, de mesma estrutura, em outro banco de dados.

Se você tentar fazer isto na versão anterior da ADO.NET (1.x) provavelmente irá seguir os seguintes passos:

Nas etapas acima você esta lendo os dados de uma origem e gravando em um destino diferente efetuando assim uma transferência de dados.

Acontece que ao tentar efetuar o update no segundo dataAdapter você não vai conseguir por que o método fill do adapter efetua um accepChanges e limpa os status dos registros para não alterados.

Usando ADO.NET 2.0 você preenche um DataTable usando o método Fill , altera as configurações do RowState das linhas desejadas para Added usando o novo método SetAdded para cada linha, e esta pronto para enviar as linhas para o segundo banco de dados, usando o segundo dataAdapter. Lembrando que os métodos SetAdded e SetModified somente afetam os registros que não foram alterados.

Nota: Existe uma maneira de efetuar a copia de um banco de dados para outro usando dois adapters na versão 1.x da ADO.NET. Basta atribuir False a propriedade  AcceptChangesDuringFill para que o Adapter  não faça o acceptchanges. Veja trecho de código abaixo:
         
           Dim da1, da2 As DataAdapter, dt As DataTable, cmd As CommandBuilder 

           'Cria um DataAdapter para o banco de dados de origem 
            da1 = New DataAdapter("SELECT * FROM tabela", con1) 

            'Define "AcceptChages" para False de forma que todas as linhas no DataTable serão vistas como "Added"
            da1.AcceptChangesDuringFill = False 

            'preenche o DataTable com os dados da tabela origem
            dt = New DataTable 
            da1.Fill(dt) 
            da1.Dispose()
 
            If Not dt Is Nothing Then 
                'Cria o DataAdapter para o banco de dados de destino
                da2 = New DataAdapter("SELECT * FROM tabela", con2)
 
                'Cria um command builder para criar os comandos de inclusão
                cmd = New CommandBuilder(da2) 

                'define InsertCommand da o DataAdapter de destino usando o commandbuilder 
                da2.InsertCommand = cmd.GetInsertCommand 

                'Atualiza o DataAdapter de destino usando o DataTable que você preencheu a partir do banco de dados origem
                da2.Update(dt) 
                da2.Dispose() 
                cmd.Dispose() 
                dt.Dispose() 
            End If 

A propriedade RowState retorna um dos valores da enumeração DataRowState da classe DataRow. Abaixo temos os valores possíveis:

Nome do Membro

Descrição Valor
Added A linha foi adicionada a DataRowCollection, e AcceptChanges não foi invocado. 4
Deleted A linha foi eliminada usando o método Delete da classe DataRow. 8
Detached A linha foi criada mas ainda não é parte de um DataRowCollection. 1
Modified A linha foi modificada e o método AcceptChanges não foi chamado. 16
Unchanged A linha não foi alterada desde que o último AcceptChanges foi chamado. 2

Abaixo temos um exemplo onde criamos um objeto DataTable,  exibimos os valores de RowState e usamos os novos métodos SetModified e SetAdded.

    Private Sub CriaNovoDataRow()

        ' cria uma nova tabela
        Dim Tabela As DataTable
        tabela = criaTabela()

        ' após criar a tabela cria um novo DataRow.
        Dim Linha As DataRow
        linha = tabela.NewRow()

        MsgBox("A linha foi criada mas ainda não é parte de um DataRowCollection.(Detached)  = " & Linha.RowState)

        Tabela.Rows.Add(Linha)
        ' nova linha.
        MsgBox("A linha foi adicionada a DataRowCollection, e AcceptChanges não foi invocado. (Added) = " & Linha.RowState)

        Tabela.AcceptChanges()
        ' linha inalterada.
        MsgBox("A linha não foi alterada desde que o último AcceptChanges foi chamado. (Unchanged) = " & Linha.RowState)

        Linha.SetModified()
        MsgBox("A linha foi modificada e o método AcceptChanges não foi chamado.Usamos setModified = " & Linha.RowState)

        ' inclui a nova linha na coleção
        linha("nome") = "Macoratti"

        'exibe os dados no datagrid
        DataGridView1.DataSource = Tabela
    End Sub

    Private Function criaTabela() As DataTable

        ' Cria uma nova tabela chamada 'Teste'
        Dim Teste As DataTable = New DataTable("Teste")

        ' Inclui 1 colunas na tabela
        Dim nome As DataColumn = New DataColumn()
        nome.DataType = System.Type.GetType("System.String")
        nome.ColumnName = "Nome"
        nome.DefaultValue = "vazio"
        Teste.Columns.Add(nome)
        ' retorna o novo DataTable.
        criaTabela = Teste
    End Function
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        CriaNovoDataRow()
    End Sub

Referências :

Até o próximo artigo...


José Carlos Macoratti