Serializing Objects to a DataSet in Visual Basic .NET
The subject of this article relates to strongly typed collections, ADO.NET, and XML serialization.
Earlier this month I demonstrated how to create a strongly typed collection (see "Implementing Strongly Typed Collection"). A strongly typed collection is a collection that contains a known type of object rather than a generic reference to the object class. Strong typing is a fundamental object oriented concept that relates to writing expressive and explicit code. You can create strongly typed collections by inheriting from the CollectionBase or ReadOnlyCollectionBase in the System.Collections namespace. Because the CollectionBase class, for instance, provides an implementation for IList, IListSource, and IEnumerable you can bind strongly typed collections to controls like the DataGrid.
What if you want to convert an object to a persistable entity, a table in a database or a file? You can certainly write monolithic code that creates a DataTable, several DataColumns, and add all of the data from your object to the new DataTable, or, you can use XML serialization and get the whole job done in about seven lines of code.
This article demonstrates how to serialize an object to a stream as XML and read the XML into an ADO.NET DataSet.
Reviewing the Sample Object Code
To demonstrate how to serialize an object we will use the Book and strongly typed Books collection from "Implementing Strongly Typed Collection", published earlier this month. That code is reprinted here for convenience.
Listing 1: Demonstrates a strongly typed collection of Book objects.
Imports System Imports System.Collections ' Implements the strongly typed collection of Books Public Class Books Inherits CollectionBase Default Public Property Item(ByVal Index As Integer) As Book Get Return CType(List.Item(Index), Book) End Get Set(ByVal Value As Book) List.Item(Index) = Value End Set End Property Public Function Add(ByVal Item As Book) As Integer Return List.Add(Item) End Function End Class ' Implements the Book class Public Class Book Private FTitle As String Private FAuthor As String Public Sub New() ' Empty constructor is needed for serialization End Sub Public Sub New(ByVal title As String, ByVal author As String) FAuthor = author FTitle = title End Sub Public Property Author() As String Get Return FAuthor End Get Set(ByVal Value As String) FAuthor = Value End Set End Property Public Property Title() As String Get Return FTitle End Get Set(ByVal Value As String) FTitle = Value End Set End Property End Class
Listing 1 introduces a default constructor for the Book class. An explicit default constructor is necessary for serialization to work correctly. The next section demonstrates the serialization code.
Serializing an Object
To serialize the collection it will be helpful to add some objects to an instance of the Books collection. In order to serialize to a DataSet we will need to create an instance of the XmlSerializer class, a stream object to serialize to, a new DataSet, and invoke the ReadXml method to deserialize the stream into the DataSet, reconstituting the Books collection as a DataSet. Listing 2 demonstrates code that performs all of these steps. (The lines of code are numbered for reference.)
Listing 2: Serializing objects to an ADO.NET DataSet
1: Imports System.Xml.Serialization 2: Imports System.IO 3: Public Sub SerializeDemo() 4: Dim B As Books = New Books() 5: B.Add(New Book("Sams Visual Basic .NET Unleashed",_ "Paul Kimmel")) 6: B.Add(New Book("Design Patterns", "Erich Gamma et. al.")) 7: B.Add(New Book("The CRC Card Book", "David Bellin")) 8: B.Add(New Book("Visal Basic .NET: Tips, Tricks, and Tutorials",_ "Paul Kimmel et. al.")) 9: 10: Dim serializer As XmlSerializer = _ New XmlSerializer(GetType(Books)) 11: Dim stream As MemoryStream = New MemoryStream() 12: serializer.Serialize(stream, B) 13: 14: Dim BookData As DataSet = New DataSet("Books") 15: stream.Position = 0 16: BookData.ReadXml(stream) 17: stream.Close() 18: 19: DataGrid1.DataSource = BookData 20: End Sub
Lines 4 through 8 create an instance of the Books collection and stuff four books from my library into the collection. Line 10 creates am XmlSerializer. The XmlSerializer class is defined in System.Xml.Serialization. We pass the type information of the type we want to serialize. (Think of line 10 as creating the schema for the kind of object to be serialized.) Line 11 creates a MemoryStream defined in System.IO. You can use any stream; for example, a FileStream would allow you to save the stream as an XML file, which is useful for persisting client-side information for Web applications.
Line 12 serializes-converts the object to XML text-the object representing the Books collection to the stream object. Line 14 creates a new DataSet. Line 15 repositions the stream to the beginning of the stream. (Think of streams as contiguous bytes of memory with an indexer that moves over each byte.) DataSet objects know how to read XML from a stream, which is what we do on line 16. After line 16 finishes we have a DataTable inside of our DataSet. Close the stream and you can bind the DataSet to a DataGrid to see the DataTable based on our collection.
Serializing objects in one form and deserializing them into another is just cool. (I imagine it is what the natives thought about orange juice from concentrate or Jello.) XML weighs in heavily in Visual Basic .NET. Because XML is an open standard we have to worry less about it evaporating like a proprietary implementation might be.
Our demonstration is roughly what happens to objects that are serialized by a Web Service. The best part is that you are not required to learn XML to take advantage of this technology.
Joe Shook, a smart guy in Oregon working on a project with me, said it best: ".NET is so cool!"
About the Author
Paul Kimmel is a freelance writer for Developer.com and CodeGuru.com. Look for his recent book, Visual Basic .Net Unleashed, at a bookstore near you. Paul Kimmel is available to help design and build your .NET solutions and can be contacted at firstname.lastname@example.org.
# # #