Using Functional Construction to Create XML Documents
I heard through the grapevine that VB.NET was mentioned on an episode of CSI: recently. Because I don't watch much TV, I missed it, but it's cool. It's a little like the invisible hand of Bill Gates reached out and said let's make VB.NET cool again. (Did VB ever stop being cool?) Or, maybe one of CSI:'s writers is a closet VB programmer. That's cool, too.
Recently, you read about VB supporting literal XML in my article "Using Literal XML with Embedded Expressions in VB9." In this article, you will read about an aspect of LINQ to XML referred to as functional construction. Functional construction is a way of dynamically creating XML documents through simple method calls.
Constructing an XML Document with Function Calls
The System.Xml.Linq namespace contains LINQ to XML classes such as XDocument, XElement, and XAttribute. (There are other class representing CDATA, comments, declarations, text, and processing instructions, too.) By creating instances of these classes and passing in the names and values, you can convert any data into an XML document. Constructors are essentially functions and this capability is referred to as functional construction. Once you see some code representing functional construction, you will pleased at how easy it is.
First, however, you will need some data to convert to XML. To that end and to provide a complete sample solution, there are several techniques demonstrated by the sample code, including boilerplate ADO.NET code to move database data into custom entity objects. The solution is decomposed in the sub-sections that follow and the entire solution is provided as one listing at the end of the article.
Defining a Custom Entity Class
An entity class is a class that maps to a database table, generally. Entity classes can encompass data retrieved from a view or stored procedure too. The basic idea is that a class contains properties that map one-to-one by name and type to columns in a table.
Note: In practice, the code in this part can and should be replaced with LINQ to SQL code, which follows roughly the same principles but is even easier to implement.
The code in Listing 1 contains an entity the AdventureWorks Customer table. (I guess even the Microsoft folks got tired of Northwind Traders, which doesn't ship with SQL Server 2005, and so there is a subtle movement to supplant it with the more advanced AdventureWorks database.)
Listing 1: An entity class mapped to the AdventureWorks Customer table.
Public Class Customer Private _customerID As Integer Public Property CustomerID() As Integer Get Return _customerID End Get Set(ByVal Value AsInteger) _customerID = Value End Set End Property Private _territoryID As Integer Public Property TerritoryID() As Integer Get Return _territoryID End Get Set(ByVal Value As Integer) _territoryID = Value End Set End Property Private _accountNumber As String Public Property AccountNumber() As String Get Return _accountNumber End Get Set(ByVal Value As String) _accountNumber = Value End Set End Property Private _customerType As String Public Property CustomerType() As String Get Return _customerType End Get Set(ByVal Value As String) _customerType = Value End Set End Property Private _rowGuid As Guid Public Property RowGuid() As Guid Get Return _rowGuid End Get Set(ByVal Value As Guid) _rowGuid = Value End Set End Property Private _modifiedDate As DateTime Public Property ModifiedDate() As DateTime Get Return _modifiedDate End Get Set(ByVal Value As DateTime) _modifiedDate = Value End Set End Property End Class
Listing 1 is about as straightforward a class as possible, so go ahead and move on. The code in Listing 2 contains plain vanilla ADO.NET 2.0 that connects to the AdventureWorks database and selects all of the Customer rows. The ADO.NET code is shown in the GetCustomers function. GetCustomers returns a List(of Customer) objects (using the generic List class). GetCustomers has two helper extension methods, the factory method Create and the generic extension method SafeRead that handles checking for null fields.