VB.NET - Serializando um DataSet


No artigo - VB.NET -  Serialização de objetos   - foram abordados os conceitos básicos sobre serialização de objetos. Continuando o assunto vou mostrar algo realmente prático : serializar um dataset em disco.

Mas antes de continuar , o que é mesmo serialização ?

Serializar , como o próprio nome diz , é armazenar informações em série. Então temos que :

"Serialização é uma técnica normalmente usada para gravar objetos em disco, transmití-los via rede, armazená-los no registro ou em um banco de dados, mas também pode ser usada para outros fins onde uma forma simples e flexível de armazenar informações se fizer necessária."

Você pode serializar um DataSet no formato XML, binário (binary) e SOAP , salvando o DataSet em um stream em disco ou em um arquivo que pode ser transmitido pela rede.

No exemplo deste artigo irei criar um dataset usando as tabelas do banco de dados Northwind.mdb: Orders e Orders Details e um relacionamento entre elas; o dataset será serializado em um arquivo em disco.

Deverá funcionar assim :

Inicie um novo projeto no VS.NET do tipo Windows Application usando a linguagem VB.NET e no formulário padrão inclua os componentes conforme a figura abaixo:

É muito importante efetuar os imports das classes que serão usadas no projeto. Abaixo temos esta relação:

Imports System.Data.oledb

Imports System.IO

Imports System.Runtime.Serialization

Imports System.Runtime.Serialization.Formatters.Binary

Imports System.Xml.Serialization

Agora no evento Click do botão de comando btnSalvar inclua o seguinte código:

Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click

' dialogo salvar arquivo

If xmlrdb.Checked Or xml1rdb.Checked Then

      sfd.Filter = "XML files (*.xml)|*.xml"

Else

      If binrdb.Checked Then

             sfd.Filter = "Binary files (*.bin)|*.bin"

      End If

End If


sfd.Filter = sfd.Filter & "Todos (*.*)|*.*"

sfd.FilterIndex = 0


If
sfd.ShowDialog() = DialogResult.OK Then

         txtArquivo.Text = sfd.FileName

End If
 

btnSerializar.Enabled = True

End Sub

Agora no evento Click do botão - Serializar - inclua o seguinte código :

Private Sub btnSerializar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSerializar.Click


If
txtArquivo.Text <> "" Then

    Dim ds As New DataSet

    Dim da As OleDbDataAdapter 

    Dim conexao As String = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=d:\teste\Northwind.mdb"

 

    'preenche a abela Order e a inclui no dataset

    da = New OleDbDataAdapter("SELECT * FROM Orders", conexao)

 

    Dim orderTable As New DataTable(TABELA_ORDER)

    da.FillSchema(orderTable, SchemaType.Source)

    da.Fill(orderTable)

    ds.Tables.Add(orderTable)

 

    ' preenche tabela OrderDetails e a inclui no dataset

    da = New OleDbDataAdapter("SELECT * FROM [Order Details]", conexao)

    Dim orderDetailTable As New DataTable(TABELA_ORDERDETAILS)

    da.FillSchema(orderDetailTable, SchemaType.Source)

    da.Fill(orderDetailTable)

    ds.Tables.Add(orderDetailTable)

 

    ' cria um relacionamento entre as duas tabelas

    ds.Relations.Add(RELACAO_ORDER_ORDERDETAILS, ds.Tables(TABELA_ORDER).Columns(CAMPO_ORDERID),     ds.Tables(TABELA_ORDERDETAILS).Columns(CAMPO_ORDERID), True)

 

    ' Vincula o dataset ao datagrid

    dbgSerializa.DataSource = ds.DefaultViewManager

    dbgSerializa.DataMember = TABELA_ORDER

  
     ' cria e abre um stream para serializar os dados

    Dim stream As Stream = Nothing

    Try

        stream = File.Open(txtArquivo.Text, FileMode.Create, FileAccess.Write)

   Catch ex As Exception

        MessageBox.Show(ex.Message, "Serializando dados", MessageBoxButtons.OK, MessageBoxIcon.Error)

        Return

   End Try

   ' serializando

   If xmlrdb.Checked Then

      ds.WriteXml(stream, XmlWriteMode.WriteSchema)

   Else

    If xml1rdb.Checked Then

        Dim xs As New XmlSerializer(GetType(DataSet))

      xs.Serialize(stream, ds)

   Else

         If binrdb.Checked Then

             Dim bf As New BinaryFormatter

          bf.Serialize(stream, ds)

       Else

               MsgBox("Selecione um tipo para serialização...", MsgBoxStyle.Critical, "Erro: tipo de serialização indefinida")

               Exit Sub

        End If

    End If

 End If

 stream.Close()

 MessageBox.Show("Serialização completa.", "Serializando dados", MessageBoxButtons.OK, MessageBoxIcon.Information)

Else

   MsgBox("Informe o nome do arquivo.", MsgBoxStyle.Critical, "Erro: Nome de arquivo inválido.")

End If

End Sub

 

Executando o projeto e selecionando as opções indicadas teremos como resultado a seguinte tela :

 

 

Explicando como o código funciona:

 

A serialização converte um objeto em um fluxo de dados (stream) que pode ser transportado ou salvo como um arquivo. A deserialização reconstrói o objeto original a partir do arquivo serializado.

 

Uma das formas mais básicas(existem outras formas) de serializar dados é escrever o conteúdo de um objeto DataSet para XML usando o método WriteXml() ou o método GetXml(). Para fazer o caminho de volta você usa o método ReadXml(). Estes métodos são limitados a serializar e deserializar objetos DataSet e fornecem um pouco de controle sobre o formato da serialização.

 

A classe XmlSerializer serializa e deserializa objetos em classes XML. Ela realiza uma serialização superficial: somente os valores das propriedades somente-leitura são serializados , os dados relacionados não são. O stream XML gerado pela classe XmlSerializer é compatível com as recomendações da linguagem 1.o da definição do schema XML (XSD) do consórcio WWW. O objeto XmlSerializer pode serializar qualquer objeto que herda de System.IO.Stream. AO construir o objeto XmlSerialiazer , você precisa definir o tipo de objeto que pode ser serializado pela instância do objeto.

 

Você pode também usar a classe XmlSerialiazer para serializar um objeto para um stream XMl SOAP. Para fazer isto use um construtor sobrecarregado que aceita o argumento XmlTypeMapping.

 

A interface IFormater fornece a funcionalidade para formatar os objetos serializados. A classe a ser serializada deve ser marcada com o atributo SerializableAttribute, de outra forma , uma exceção do tipo SerializationException será levantada. A classe pode implementar a a interface ISerializable para sobrescrever o comportamento padrão da serialização.

 

A classe System.RunTime.Serialization.Formatter fornece a funcionalidade básica para os formatadores.

 

- Para serializar/deserializar para o formato binário usamos a classe BinaryFormatter que pode realizar uma serialização profunda e implementa as interfaces IFormatter e IRemotingFormatter, que fornecem a funcionalidade para formatar objetos serializados que podem ser enviados por chamadas de procedures remotas (RPC).

 

O método Serialize() da interface IFormatter serializa o objeto para o objeto stream. Isto inclui todas as classes que possuem como base a classe System.IO.Stream como :

Desde que o objeto da serialização foi criado , a serialização continua pela chamada do método Serialize() do objeto com argumentos referenciando o stream de destino e o objeto a ser serializado. È o que pode ser visto no trecho de código a seguir:

 

If xmlrdb.Checked Then

      ds.WriteXml(stream, XmlWriteMode.WriteSchema)

   Else

    If xml1rdb.Checked Then

        Dim xs As New XmlSerializer(GetType(DataSet))

      xs.Serialize(stream, ds)

   Else

         If binrdb.Checked Then

             Dim bf As New BinaryFormatter

          bf.Serialize(stream, ds)

       Else

               MsgBox("Selecione um tipo para serialização...", MsgBoxStyle.Critical, "Erro: tipo de serialização indefinida")

               Exit Sub

        End If

    End If

 

No próximo artigo vou mostrar como fazer o caminho de volta.

 

Pegue o projeto completo aqui : serializarDs.zip

 

Até breve...


José Carlos Macoratti