VB.NET - Acessando linhas deletadas em um DataTable
Você sabia que quando deleta linhas de um DataSet na verdade elas são marcadas para deleção até que as mudanças seja confirmadas pela chamada direta o indireta do método AcceptChanges() ?
Sabia também que pode ter acesso a estas linhas antes de sua deleção ?
Pois é , vivendo e aprendendo. Neste artigo vou mostrar como você pode acessar linhas deletadas em um objeto DataTable.
Na verdade fazer isto é muito simples:
Você pode usar um objeto DataView ou
Você pode usar o método Select() do objeto DataTable
para ter acesso às linhas deletadas.
Cenário:
1- Vamos criar um projeto que acessa a tabela Orders do banco de dados Northwind.mdb exibindo todos os registros em um objeto DataGrid usando uma instrução SQL Select do tipo : Select * From Orders.
2- Usaremos dois radiobutton e um caixa de Texto : um para exibir os registros deletados e outro para exibir os registros atuais. Os registros serão exibidos na caixa de texto.(para isto sua propriedade Multiline deve ser definida como True)
3- A princípio os registros serão exibidos e não haverá nenhum registro deletado. Para deletar selecione uma linha ou mais do datagrid e pressione a tecla DEL.
4- Após fazer isto basta clicar no radiobutton - rdbLinhasDeletadas para que os registros que você deletou sejam mostrados.
O Projeto
Inicie um novo projeto no VS.NET do tipo Windows Application usando a linguagem VB.NET e no formulário padrão - form1.vb- inclua os seguintes componentes:
Componente | Nome |
1 DataGrid | DataGrid1 |
2 radiobutton | rdbLinhasAtuais de rdbLinhasDeletadas |
1 TextBox | txtLinhasDeletadas (Multiline=True) |
Abaixo o jeitão do projeto:
Para utilizar o StringBuilder e o acesso a um banco de dados Access usando o provedor OleDb. vamos precisar dos seguintes imports:
A Imports SystemImports System.ConfigurationImports System.TextImports System.Data.OleDb
|
Precisamos também definir o objeto DataView - dv, no inicio do formulário, assim :
Private dv As DataViewInclua um arquivo de configuração conforme mostrado em no artigo .NET - Tratando arquivos de configuração . O arquivo conterá a string de conexão com o banco de dados Northwind.mdb .
<? xml version="1.0" encoding="utf-8" ?>< configuration>< appSettings> <add key="acessoBD" value="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\teste\Northwind.mdb" /></ appSettings></ configuration> |
Agora vamos ao código do projeto:
NO evento Load do formulário inclua o código :
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
da.Fill(dt)
dv = New DataView(dt, Nothing, Nothing, DataViewRowState.CurrentRows)
DataGrid1.DataSource = dv
rdbLinhasAtuais.Checked = True End Sub |
No evento checkedChanged do radiobutton - rdbLinhasAtuais - que exibe as linhas atuais inclua o código:
Private
Sub rdbLinhasAtuais_CheckedChanged(ByVal
sender As System.Object,
ByVal e As System.EventArgs)
Handles rdbLinhasAtuais.CheckedChanged
dv.RowStateFilter = DataViewRowState.CurrentRows
DataGrid1.ReadOnly = False 'limpa a caixa de texto txtLinhasDeletadas.Clear() End Sub |
No evento checkedChanged do radiobutton - rdbLinhasDeletadas - que exibe as linhas deletadas inclua o código:
Private Sub rdbLinhasDeletadas_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rdbLinhasDeletadas.CheckedChanged
' filtra o view para incluir somente linhas deletadas dv.RowStateFilter = DataViewRowState.Deleted
'define o datagrid como somente leitura (não permite deleção) DataGrid1.ReadOnly = True ' obtem o DataTable a partir do DataView Dim dt As DataTable = dv.Table
' faz o filtro usando DataTable RowState Dim delRows As DataRow() = dt.Select(Nothing, Nothing, DataViewRowState.Deleted)
'define um stringbuilder para Dim sb As New StringBuilder("Registros deletados:" & Environment.NewLine)
'define um objeto row para Dim row As DataRow
' percorre a coleção de linhas deletadas(deleted rows) For Each row In delRowssb.Append(("Pedido : " & row("OrderID", DataRowVersion.Original) & Environment.NewLine)) Next row
'exibe no textbox a relação de linhas deletadas txtLinhasDeletadas.Text = sb.ToString() End Sub |
Para saber mais sobre o StringBuilder leia o artigo: VB .NET - StringBuilder : tratando Strings de modo mais eficiente.
Executando o projeto teremos:
|
|
Selecionando as linhas para Deleção e Teclando DEL em seguida |
Exibindo as linhas deletadas |
Um pouco de teoria sobre o assunto:
ADO.NET gerencia o estado das linhas enquanto elas estão sendo modificadas. Abaixo temos os estados atribuídos as linhas pela enumeração DataRowState.
Valor |
Descrição |
---|---|
Added |
A linha foi incluida na coleção de linhas na tabela mas o método AcceptChanges( ) não foi chamado ainda. |
Deleted |
A linha foi deletada da coleção de linhas na tabela mas o método AcceptChanges( ) não foi chamado ainda. |
Detached |
A linha não pertence a coleção de linhas no DataTable. |
Modified |
Os dados na linha foram alterados mas o método AcceptChanges( ) não foi chamado |
Unchanged |
Os dados na linha não foram alterados desde que ela foi carregada ou desde que o método AcceptChanges( foi chamado |
Quando o método AcceptChanges é chamado no DataSet, o DataTable ou o DataRow quer de forma explícita quer de forma implícita via método update() do objeto DataAdpater, ocorre o seguinte:
Todas as linhas com estado - Deleted - são removidas
Todas outras linhas tem o seu estado alterado para Unchanged e os valores originais da versão da linha são sobrescritos com o valor da versão atual da linha.
Quando o método RejectChanges é chamado no DataSet , DataTable ou DataRow ocorre o seguinte:
Todas as linhas com estado Added são removidas
Todas as demais linhas tem o seu estado alterado para Unchanged e os valores da versão atual da linha são sobrescritos com os valores originais da versão da linha atual.
Cada DataRow tem uma propriedade chamada RowState que retorna o estado atual da linha.
ADO.NET mantém diversas versões dos dados em cada linha enquanto ela esta sendo modificada para permitir a reconciliação do modo desconectado com a fonte de dados. Abaixo temos a tabela que mostra os valores para a enumeração DataRowVersion.
Valor |
Descrição |
---|---|
Current |
O valor atual. Esta versão não existe para linhas com o estado Deleted. |
Default |
Valor padrão como determinado pelo DataRowState:
|
Original |
O valor Original . Esta versão não existe para linhas com estado Added. |
Proposed |
Valor proposto.Este valor existe durante a edição da linha quer implicitamente ou explicitamente com o método BeginEdit( ) e para linhas com estado Detached. |
O método HasVersion( ) do objeto DataRow verifica se uma versão particular da linha existe.
A enumeração (enumeration) DataViewState é usada para retornar uma versão particular dos dados ou para determinar se a versão existe, Os métodos Select() do objeto DataTable e a propriedade RowStateFilter do DataView usam o DataViewState com este propósito. Você pode retornar mais de uma versão usando um valor booleano OR de valores DataViewRowState. A tabela abaixo mostra os valores para DataViewRowState:
Valor |
Descrição |
---|---|
Added |
A versão atual de todas as linhas incluidas. |
CurrentRows |
A versão atual de todas as linhas inalteradas, incluidas e modificadas. Valor padrão |
Deleted |
A versão original de todas as linhas deletadas |
ModifiedCurrent |
A versão atual de todas as linhas modificadas. |
ModifiedOriginal |
A versão original de todas as linhas modificadas. |
None |
Sem linhas |
OriginalRows |
A versão original das linhas não alteradas, modificadas e deletadas. |
Unchanged |
A versão atual de todas as linhas inalteradas. |
A versão atual de cada linha é retornada por padrão quando elas são acessadas no DataTable ou no DataView. A solução usada obtêm linhas deletadas de um DataTable e de um DataView. As linhas deletadas incluem somente aquelas marcadas para deleção usando o método Delete() do DataRow() ou do DataView, mas não o método Remove() ou RemoveAt() de DataRowCollection, que removem imediatamente a linha da coleção DataRow().
A solução apresentada usa duas técnicas:
1- Para obter as linhas deletadas do DataTable usamos um método Select() sobrecarregado do DataTable para retornar um vetor de objetos DataRow. O método aceita um argumento que tem um valor da enumeração DataViewRowState. Para retornar as linhas deletadas passamos o valor Deleted como argumento.
2- Para obter as linhas deletadas de um DataView definimos a propriedade RowStateFilter como Deleted. As linhas deletadas também são visíveis junto com as demais linhas se definirmos a propriedade RowStateFilter como ModifiedOriginal e OriginalRows.
Aguarde mais artigos sobre VB.NET.
José Carlos Macoratti