Introduction
I spent the week of April 13th in Redmond at the MVP Summit. If you don’t know, MVP stands for Most Valuable Professional. One usually becomes and MVP by nomination and then having acquired some unknown amount of community kudos. For instance, lots of blogging and voluntarily helping people in newsgroups might get you there eventually. So, the MVP Summit is a way for Microsoft to thank MVPs for their free contributions, continue to foster affinity with these non-Microsoft employees, and provide MVPs with an insider’s look at upcoming features. Thanks, Microsoft.
I have to tell you I was shocked! Shocked at the few very vocal Visual Basic MVPs who sounded like whiiiinnnnneeeerrrrs. (You know who you are.) The gist of it was the people don’t treat VB programmers like real programmers or at least on a par with, say, C# programmers. They were right. VB contractors make less than C# contractors in general. But, this is not Microsoft’s fault, folks. VB can be a tough, gritty language capable of solving any problem that C# can solve, but there is an underlying problem and it lives in the VB community itself.
Many VB programmers are holding onto old VB6 and the VB6 ways of doing things; consequently, there is no room for new articles, new books, or any reason to really learn anything new. So, if VB is the poor cousin, it’s our fault. Personally, I know VB is just as good a language as any out there—well, VB9 anyway. To demonstrate that, this article crams seven cool and a bit complicated—if it’s your first time seeing them—features into an 80-line sample program.
In this article, you will get a chance to explore LINQ to SQL, generic delegates, literal XML with embedded LINQ expressions, attributes, and Lambda expressions. (Did I say in 80 lines of code?) In fact, even C# can’t do literal XML, which is way cool. So, if you know a holdout in VB6 or someone doing things the same old way, feel sorry for them because these features or too cool, too fun, and promote way too much productivity to ever go back.
Previewing the Technology Usage
The basic setup here is that a lot of data exists in databases. This data is generally read from a database, converted to some form or another, changes are made, and then the data is written back to the database. Sometimes, the data is converted to something highly transmittable, such as text/XML.
In the example in Listing 1, you will see just how easy it is to initialize database entities—classes that map to a database table—with LINQ to SQL, and how with literal XML with embedded expressions can be used to transform the entities into any shape XML tree you need. The supporting cast is comprised of Lambda expressions, generic delegates, and attributes.
Listing 1: An 80-line sample program that uses a lot of cool new capabilities provided by VB9 to do some powerful stuff.
Imports System.Data.Linq Imports System.Data.Linq.Mapping Imports System.Xml.Linq Module Module1 Sub Main() Dim ConvertToXML As Func(Of List(Of Shipper), String) = _ Function(shippers) (<Shippers> <%= From shipper In shippers _ Select <Shipper ShipperID=<%= shipper.ShipperID %> <%= shipper.CompanyName %>> <Phone><%= shipper.Phone %></Phone></Shipper> %> </Shippers>).ToString() Dim northwind As Northwind = New Northwind Console.WriteLine(ConvertToXml(northwind.Shippers.ToList())) Console.ReadLine() End Sub End Module Public Class Northwind Inherits DataContext Private Shared ReadOnly connectionString As String = _ "Data Source=BUTLER;Initial Catalog= _ Northwind;Integrated Security=True" Public Sub New() MyBase.New(connectionString) End Sub Public ReadOnly Property Shippers() As Table(Of Shipper) Get Return Me.GetTable(Of Shipper)() End Get End Property End Class <Table(Name:="Shippers")> _ Public Class Shipper Private _shipperID As Integer <Column(Storage:="_shipperID")> _ Public Property ShipperID() As Integer Get Return _shipperID End Get Set(ByVal Value As Integer) _shipperID = Value End Set End Property Private _companyName As String <Column(Storage:="_companyName")> _ Public Property CompanyName() As String Get Return _companyName End Get Set(ByVal Value As String) _companyName = Value End Set End Property Private _phone As String <Column(Storage:="_phone")> _ Public Property Phone() As String Get Return _phone End Get Set(ByVal Value As String) _phone = Value End Set End Property End Class
Can you spot the technology usage? The Shipper class is an object relational map to the Northwind Shippers table. The Table Attribute identifies the underlying table and the ColumnAttribute identifiers the related column. The Northwind class inherits from DataContext and all you need is the connection string and LINQ to SQL is able to read and write to the database with very little code.
ConvertToXML is a generic delegate that accepts a generic List of Shipper objects and returns a (XML) string. The keyword Function(shippers) signals that you are using a Lambda expression, and <Shippers> is the opening tag of your literal XML. Yep, XML is a valid data type in VB9. The data type of the literal XML is XElement (or XAttribute) from System.Xml.Linq depending on whether the XML is an element or an attribute. The literal values are input arguments to the constructors for these types. When the compiler sees the embedded expression <%= %>, it executes that bit of code and that also is an argument to the appropriate element types constructor.
The generic delegate, Lambda expression, literal XML, and nested LINQ query statement are doing a lot. The From clause defines a range variable shipper. The range value shipper is used in the embedded expressions to obtain the element and attribute values for the XML. The Select statement of the query is actually projecting a new type, literal XML. Finally, the whole XML/LINQ expression is wrapped in parentheses and ToString returns the XML result. Whew! The output from the sample is shown in Listing 2.
Listing 2: The output from Listing 1 is XML.
<Shippers> <Shipper ShipperID="1">Speedy Distressed <Phone>(503) 555-9831</Phone> </Shipper> <Shipper ShipperID="2">United Package <Phone>(503) 555-3199</Phone> </Shipper> <Shipper ShipperID="3">Federal Shipping <Phone>(503) 555-9931</Phone> </Shipper> </Shippers>
Summary
Last night I heard a Sea World commercial. The tag line was “I believe that fun is a renewable resource”. That tagline made me want to go back to Sea World, but it also resonated with me because I believe it, too. Software is supposed to be fun. And these new features are a lot of fun.
VB6 was great in its day, but there is a whole lot more fun out there just waiting to be explored and used. With Lambda expressions, LINQ to SQL, literal XML and embedded expressions, and generic delegates VB9 is not only not your father’s Oldsmobile, it may very well be your son’s Tesla Roadster—check out http://www.teslamotors.com/. (Sorry; I couldn’t resist.)
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# due in July 2008. Paul Kimmel is an Application Architect for EDS. You may contact him for technology questions at pkimmel@softconcepts.com.
If you are interested in joining or sponsoring a .NET Users Group, check out www.glugnet.org. Glugnet opened a users group branch in Flint, Michigan in August 2007. If you are interested in attending, check out the www.glugnet.org web site for updates.
Copyright © 2008 by Paul T. Kimmel. All Rights Reserved.