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.oledbImports System.IOImports System.Runtime.SerializationImports System.Runtime.Serialization.Formatters.BinaryImports 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 Thensfd.Filter = "XML files (*.xml)|*.xml" Else If binrdb.Checked Then sfd.Filter = "Binary files (*.bin)|*.bin" End If End If
sfd.FilterIndex = 0
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
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
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 :
System.IO.BufferedStream
System.IO.FileStream
System.IO.MemoryStream
System.IO.Sockets.NetworkStream
System.IO.Cryptography.CryptoStream
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