This blog is targeted at beginning / novice programmers for the Visual Basic (VB) language.

Friday, March 21, 2008

Introduction to LINQ in VB

Overview:

By now, most of us have heard of LINQ and have a general concept of what it is and what can be done with it. For the few that don't I'll lightly skim over it. The remainder of this post will discuss what the major differences are between LINQ in VB and LINQ in C# and also offer some resources to get technical information, practical examples, and some very helpful videos. Best of all; ALL of these resources are FREE!!!

What is LINQ? How do I use it?

"LINQ" is an acronym formed from the .Net 3.5 framework named "Language INtegrated Query". The LINQ framework is composed of LINQ enabled data sources (also commonly referred to as data providers). There is a subset of data providers that are ADO.Net enabled; these are: LINQ To Datasets, LINQ to SQL, and LINQ To Entities (LINQ To Entities is currently in development and has been confirmed to be included in Service Pack 1 update for Visual Studio 2008). There are 2 other included data providers for LINQ called: LINQ To Objects, and LINQ To XML. You can also make your own data providers to be used; there are even data providers already created by 3rd party vendors, such as LINQ To Amazon that you can obtain (some may have associated costs; these are determined by each vendor and are typically not supported by Microsoft).

LINQ is automatically enabled, to some extent, with Visual Studio 2008. Your only real requirement is to use the .Net 3.5 framework. Conceptually you could use Visual Studio 2005 and LINQ; however, there are many additional features/enhancements included with Visual Studio 2008 that can leverage LINQ in a more powerful manner than you would be able to with Visual Studio 2005 (such as Type Inference and XML literals). To use LINQ you simply set your references to the appropriate namespace of the framework class you want to use (VS 2008 includes some namespaces automatically) and then you can use the 'Imports' keyword to enable local declarations at the class level.

Example of enabling at the class level would be:

'System Namespaces
Imports System.Data.Linq

Public Class Form1
'Insert your LINQ code here
End Class

As you can see, enabling LINQ at the class level is quite simple to perform.

What can I do with LINQ?

Well, that is a very broad answer. Basically anything that could be considered a collection or data collection can be used by LINQ. In fact you can even use LINQ for many documents that are created by Office 2007; this is because Office 2007 documents are actually a collection in a zip file of XML and other items. You can actually rename any Word document with a ".zip" extension and then easily view and modify the content within the document. This means you could literally create or modify a Word 2007 document without having Word 2007 installed on the machine!

Why you might ask would someone want to do this? That's quite simple; let's say you have specific information you want to create a set of documents for (similar to using MailMerge in Word); well, if you already have a template or base document created, you could actually use VB to modify the document.xml file within the docx file collection and create the merged document. A great example would be to notify a list of customers that may not have placed an order with your company within the past year. You could use LINQ To SQL (assuming the data is in an SQL database) and iterate through the customer information looking for last activity or order date of more than 1 year ago..take this information and use LINQ To XML to insert the data into your custom created docx file, then save each file created as a new docx filename (such as the customer's account name). Since you don't have to have Word installed to work with an existing docx file, you could leverage the power of your server machine to do the processing work for this task. This means, although not recommended, you could literally create your files right on your SQL Server machine and store the documents within your SQL Server database that could later be used to be sent out to your 'inactive' customers to see if you can drum up some repeat business! How cool is that?!

That's only the tip of the iceberg. Remember, LINQ is designed to easily iterate through a collection of data and to work with that iterations. You can probably already think of a whole bunch of data that it would be great to go through quickly and seamlessly. Because LINQ was designed to use a "standard" query language this means you can create a LINQ query that can be used on SQL, XML, Entities, Objects, and any other data provider you get access to.

This all translates to one wonderful meaning...Once you learn LINQ regardless of the way you use it, you can use LINQ with any other data provider; but, do be aware that there are a few data providers that have a few extended uses that can't be interchanged...but with very little ingenuity you can quickly figure out how to leverage these powerful extensions, such as XML Literals, with the other Data Providers. You can even seamlessly use multiple LINQ query structures within a single query!

What is different in LINQ for VB than in LINQ for C#?

The biggest difference is what is called XML Literals and XML Axis, these can ONLY be used in VB; they are not supported in declarative languages.

First, the big one is XML Literals. With XML Literals you can create XML code that resembles what the output of your XML document will look like. This allows for a true representation of the XML code and document; it's basically the XML WYSIWYG in VB editor! Here's an example of a very simple XML Literal that would have an output that is exactly the same as the code:

Dim myBloxXML = _
           
<Blog>
               
<Name>Visual Basic Helper Blog</Name>
               
<URL>http://visualbasichelper.blogspot.com</URL>
               
<LastPostingName>Introduction to LINQ in VB</LastPostingName>
           
</Blog>

The output would look like this:

<Blog>
     <Name>Visual Basic Helper Blog</Name>
     <URL>http://visualbasichelper.blogspot.com</URL>
     <LastPostingName>Introduction to LINQ in VB</LastPostingName>
</Blog>

As you can see, this is very powerful and allows you to easily determine if something is out of place and how your final document will look like; without ever running the code..and you get the benefits of the type-safety and declaration checking.

But, it doesn't stop there. You can also use embedded expressions; this is both C# and VB enabled. An embedded expression is triggered by using a <%= > enclosure. Here's an example of a simple expression that would retrieve all of the customers from a database table called "Authors". I'm not going to cover the entire method to connect to the database, that'll get covered another time...mainly just look at how I can insert a LINQ query right into my LINQ To XML constructor...and notice that I am mixing the two forms of querying...I'm using LINQ to XML to make the XML tree; but I'm also using LINQ to SQL to get the data to put in the tree...never having to stop my train of thought or change any coding declarations; I just type and go. Here's an example:

Dim myCustXML As XElement = _
           
<Customers>
               
<Customer>
                   
<%= From c In dbcntx.Authors _
                       
Where c.Auth_LName Like "*A*" _
                       
Select _
                       
<Name>
                           
<%= c.Auth_FName %> <%= c.Auth_LName %>
                       
</Name> %>
               
</Customer>
           
</Customers>

The ouput would be:

<Customers>
      <Customer>
            <Name>Stephen Allway</Name>
            <Name>Robert Alonzo</Name>
            <Name>Tom Anand</Name>
            <Name>John Arnold</Name>
            <Name>Alfred Axel</Name>
      </Customer>
</Customers>

As you can see here, I easily went between the two LINQ data providers and formed a very simple tree; I'm only showing a few returned results due to space consumption, but you should get the idea.

This now leaves us with XML Axis; this is basically a shortcut method to tell your code what part of XML to look in. Example would be you could use the trigger "@" to tell your code that you are looking for an XML Attribute. You could use the trigger "..." to tell your code that you are looking for any descendent within the branches of your tree; or you could use "<>.<>" to tell your code where the specific child element is located.

Here are some very quick examples:

'XML calls are based on this XML tree
        Dim myCustomers = _
       
<Customers>
           
<Customer>
               
<Name id="1" age="30">Stephen Allway</Name>
               
<Name id="2" age="55">Robert Alonzo</Name>
               
<Name id="3" age="17">Tom Anand</Name>
               
<Name id="4" age="25">John Arnold</Name>
               
<Name id="5" age="75">Alfred Axel</Name>
           
</Customer>
       
</Customers>

       
'Get age for first name element
        Console.WriteLine("Age: " & myCustomers...<Name>.@<age>)
       
'Get name for first customer by using decendants
        Console.WriteLine("Name: " & myCustomers...<Name>.Value)
       
'Get name for first customer by using child
        Console.WriteLine("Name: " & myCustomers.<Customer>.<Name>.Value)

The entire output would be:

Age: 30
Name: Stephen Allway
Name: Stephen Allway

The other worthwhile note is that the major difference between descendants and child methods is performance. The child method will perform better than the descendants method; this is because the descendants method will search all parts of the element and return ANY and ALL that match it...so if you were to have the following tree:

<Family>
    <Pets>
        <Name>Fluffy</Name>
        <Age>3</Age>
    </Pets>
    <Children>
        <Name>Alexis</Name>
        <Age>10</Age>
    </Children>
</Family>

If you were to use the <Family> as the root node, and call the descendants method looking for <Name> you'd get "Fluffy" and "Alexis" returned; this is because the method only limits it's search to the root node and all child nodes.

If you were to use the same scenario as above and use the child method you could specify if you want to return the Children or Pets node. An example would be:

Console.WriteLine("Name: " & myFamily.<Family>.<Children>.<Name>.Value)

As you can see to call each trigger is simple; these are included with the XML Intellisense by default. All you need to do is to have a variable that is of the XML data type.

Conclusion

This was just an introductory to LINQ in VB; this topic is huge and probably one of the largest (if not the largest) addition to the .Net 3.5 Framework and also for Visual Studio 2008.

As you saw this framework is not limited to Visual Studio 2008; however, if you want to leverage all aspects of LINQ you will have to use Visual Studio 2008 then. You also saw that LINQ was developed to be interchangeable in your code, and there are a few subtle differences between the C# implementation and VB's implementation.

Hopefully, I've been able to get you to a starting point that can the primer for learning more about LINQ. Once you play around with it, you'll probably find yourself constantly finding new ways to use it and it will be one of your most desired tools when working with any sort of data collection.

Additional Resources:

MSDN Language Integrated Query (LINQ) - (http://msdn2.microsoft.com/en-us/library/bb397926.aspx)
The LINQ Project - (http://msdn2.microsoft.com/en-us/netframework/aa904594.aspx)
Beth Massi - Sharing the Goodness that is VB - (http://blogs.msdn.com/bethmassi/)
LINQ 'How Do I' Videos - (http://msdn2.microsoft.com/en-us/vbasic/bb466226.aspx?wt.slv=topsectionsee#linq)

Until next time...Happy Coding!

2 comments:

James said...

Thank you for the compliment. I hope to start adding more useful posts in the near future.

Happy coding!
James

html5 video player said...

I have no words for this great post such a awe-some information i got gathered. Thanks to Author.