Introduction
It is not is hardly worth talking about; well, okay, just one more time. It seems there is an impression that advanced techniques are adopted by VB developers more slowly. Consequently, some things show up in C# first and VB later (if at all; remember anonymous delegates never showed up in VB). It is what it is. If it happens, mix C# in with your VB code rather than go without.
Language INtegrated Query (LINQ, pronounced “link”) is a new technology in .NET 3.5 that pretty much lets you use one query language (LINQ, which is a lot like SQL) to write queries against SQL, Objects, XML, and pretty much anything you’d like. By implementing an IQueryProvider, as demonstrated in my upcoming book LINQ Unleashed for C# from Sams, you even can use LINQ to query things such as Active Directory or SharePoint.
LINQ is out and ready for prime time. LINQ to XSD is an extension of the core LINQ technologies and is at present still in alpha. LINQ to XSD builds on LINQ to XML. By including an XML Schema Document, LINQ to XSD will code generate strongly typed wrapper classes, permitting you to read and write the XML document as easily as you would create and use any objects. One minor drawback (for now) is that you will need to use a C# class library for the LINQ to XSD technology at the time this article was written. However, because everything in the C# class library is code generated, you don’t need to know C# to use LINQ to XSD with your VB applications.
Creating the Class Library
When new kinds of projects are added to Visual Studio, they are actually added as stubs and wizard launching files. These stubs and launching files show up as icons in the Add New Project and Add New Items dialogs. Underneath, they are actually integrated through a variety of text files, JScript, and a general wizard that uses these elements to figure out what to do. That really doesn’t matter. What matters is that these files have to exist for a given language for you to be able to use these new elements easily. Without them, you have to figure out all of the plumbing manually.
Tip: Microsoft has a new download portal at http://www.codeplex.com. You can get access to a lot of cool open source bits.
With the Alpha 0.2 preview version of LINQ to XSD, there are wizards for C# only. Hence, to use the technology at this point the easiest way is to create a C# class library project. Assuming that you have downloaded and installed the LINQ to XSD preview from http://www.microsoft.com/downloads/, follow these steps to create the C# LINQ to XSD Class Library:
- Start Visual Studio .NET 2008.
- Select File|New Pew Project.
- Navigate to the Visual C#|LINQ to XSD Preview project types.
- Click on the LINQ to XSD Library template.
- Name the class library generated code.
- Click OK
Next, you will need to define an XML document and the schema (.XSD) document. And, there are a couple more steps; these are covered in the next couple of sub-sections.
Defining an XML Document
When you create the XSD Preview project in the last section, a new assembly was added to the references list: Microsoft.Xml.Schema.Linq.dll. This assembly contains the code generators that will create wrapper classes for the XML and XSD documents.
Listing 1 contains an XML document that references an XSD document (you will create this in the next section). The XML document (named Zoos.xml) contains some of the zoos of the world.
Listing 1: An XML document containing zoos of the world.
<?xml version="1.0" encoding="utf-8" ?> <Zoos xmlns="http://tempuri.org/ZooSchema.xsd"> <Zoo> <Name>Abilene Zoo</Name> <City>Abilene</City> <State>Texas</State> <Country>USA</Country> </Zoo> <Zoo> <Name>Asa Zoological Park</Name> <City>Hiroshima</City> <State></State> <Country>Japan</Country> </Zoo> <Zoo> <Name>Assiniboine Park Zoo</Name> <City>Winnipeg</City> <State>Manitoba</State> <Country>Canada</Country> </Zoo> <Zoo> <Name>Belize Zoo</Name> <City>Belize City</City> <State></State> <Country>Belize</Country> </Zoo> <Zoo> <Name>Birmingham Zoo</Name> <City>Birmingham</City> <State>Alabama</State> <Country>USA</Country> </Zoo> <Zoo> <Name>Brevard Zoo</Name> <City>Melbourne</City> <State>Florida</State> <Country>USA</Country> </Zoo> <Zoo> <Name>The Bronx Zoo</Name> <City>New York</City> <State>New York</State> <Country>USA</Country> </Zoo> <Zoo> <Name>Buffalo Zoological Gardens</Name> <City>Buffalo</City> <State>New York</State> <Country>USA</Country> </Zoo> <Zoo> <Name>Parc Zoologique de Lille</Name> <City>Lille</City> <State></State> <Country>France</Country> </Zoo> <Zoo> <Name>Parken Zoo</Name> <City>Eskilstuna</City> <State></State> <Country>Sweden</Country> </Zoo> <Zoo> <Name>San Diego Wild Animal Park</Name> <City>Escondido</City> <State>California</State> <Country>USA</Country> </Zoo> <Zoo> <Name>Zoo Augsburg</Name> <City>Augsburg</City> <State></State> <Country>Germany</Country> </Zoo> <Zoo> <Name>Zoological de Culiacan</Name> <City>Culiacan</City> <State></State> <Country>Mexico</Country> </Zoo> </Zoos>
For all intents and purposes, the XML document in Listing 1 is a persisted collection of Zoo objects, and that is precisely how you want to treat them in your code.
Defining the XML Schema
An XML Schema document (XSD) describes how a well-formed XML document matching this schema will be formed. The XSD document in Listing 2 indicates that documents conforming to this schema will contain a complex type named Zoos. The complex type Zoos will contain 0 to many complex types called Zoo. Zoo elements contain a Name, City, State, and Country; these are all string types.
Listing 2: An XSD document that describes what the contents of XML document that conform to this schema will contain.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tempuri.org/ZooSchema.xsd" xmlns="http://tempuri.org/ZooSchema.xsd" elementFormDefault="qualified"> <xs:element name="Zoos"> <xs:complexType> <xs:sequence> <xs:element ref="Zoo" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Zoo"> <xs:complexType> <xs:sequence> <xs:element name="Name" type="xs:string"/> <xs:element name="City" type="xs:string"/> <xs:element name="State" type="xs:string"/> <xs:element name="Country" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
For all intents and purposes, the XSD document (named ZooSchema.xsd) in Listing 2 describes XML documents that will contain data representing a collection of Zoo data. For the XML document to be considered well-formed, it can be expected to contain the elements described by the associated schema.
Code Generating the Wrapper Classes
XML and XSD documents have been around a while. What’s new is that, by associating the Microsoft.Xml.Schema.Linq.dll assembly with the project and changing the Build Action for the schema document, you can instruct Visual Studio .NET to use the LINQ to XSD technology to code generate wrapper classes. Here is the extra step needed:
- In the C# Class Library project, select the ZooSchema.xsd.
- Press F4 to display the Properties Window.
- Change the Build Action to LinqToXsdSchema (see Figure 1).
- Build the C# Class Library project.
Figure 1: Associate a build action with the XSD file.
After you build the class library project, press F2 to open the Object Explorer. The Object Browser will contain information about the class library, including a namespace to match the namespace defined in the XSD document and classes representing the code generated elements. For your purposes, you are interested in the Zoos and Zoo classes (see Figure 2).
Figure 2: The code generated elements, generated by the new LINQ to XSD technology.
At this point, you can reference the GeneratedCode class library, import the namespaces, and use Zoos and Zoo like any other class. The LINQ to XSD technology will get the data from the XML document and populate a collection that you can query with LINQ.
Writing VB Code Using LINQ to XML for Objects
So, now you have an XML document and schema. After the preceding section, you also have code generated, strongly typed classes. Load the XML document and query away.
To explore the LINQ to XSD generated Zoo and Zoos classes, follow these steps:
- Add a VB console application containing the C# class library to the solution.
- To the new project, add a reference to Microsoft.Xml.Scheam.Linq.dll by selecting Project|Add Reference, clicking the Browse tab, and navigating to the C:Program FilesLINQ to XSD PreviewBin folder.
- Add a reference to the GeneratedCode class library project.
- In the default Module1 file, add an Imports statement for both Microsoft.Xml.Schema.Linq and tempura.org.ZooSchema.xsd.
- Add the code in Listing 3.
Listing 3: The sample code that queries the XML document using the strongly typed classes.
Imports System.Xml Imports System.Xml.Linq Imports System.Linq Imports tempuri.org.ZooSchema.xsd Imports Microsoft.Xml.Schema.Linq Module Module1 Sub Main() Dim z = Zoos.Load("../../../GeneratedCode/Zoos.xml") Dim selectedZoos = From one In z.Zoo _ Select one For Each aZoo In selectedZoos Console.WriteLine(aZoo.Name) Next Console.ReadLine() End Sub End Module
Basic LINQ is pretty easy. The From clause comes first because this aids Intellisense. The Select clause comes last; this section creates what is called a projection. A projection can be a new typed by selectively picking fields from elements defined by the From clause or can be the items specified in the From clause.
The code in Listing 3 reads the XML document and loads all of the data into the anonymous type defined by the variable z. The variable z is actually an instance of Zoos. The next statement selects all zoos and the ForEach statement displays the zoo name in the console. That’s it. Very object oriented and very easy.
LINQ is an extraordinarily powerful technology. For more on LINQ, check back with this column or pick up a copy of my book LINQ Unleashed for C# from Sams, available August 2008 (or pre-order today at Amazon.com).
Summary
This article culminates in the objectification of an XML document, which is subsequently queried with a single line of code. That’s power. Underneath, there are so many cool and powerful technologies that it’s amazing.
If you have been following along with my articles, you have probably guessed that to support querying an XML document with a single statement there is the .NET framework, XML and XSD, LINQ, anonymous types, the CodeDOM, extension methods, and generics. Each of these capabilities is powerful in its own right. When orchestrated toward a single purpose, LINQ to XSD, they let you take something a little complicated and advanced and manipulate it with ease.
About the Author
Paul Kimmel is the VB Today columnist for www.codeguru.com and has written several books on object-oriented programming and .NET. Check out his upcoming book LINQ Unleashed for C#; pre-order your copy today at Amazon.com. Paul Kimmel is an Application Architect for EDS. You may contact him for technology questions at pkimmel@softconcepts.com.
Lansing is having a free Day of .NET training at Lansing Community College on June 21st. Check out the web site for details. The group likes to think of it as a poor man’s TechEd (because it’s free), but the content will be excellent.
Copyright © 2008 by Paul T. Kimmel. All Rights Reserved.