RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


ADO.NET vNext Part 3: Querying with LINQ : Page 3

LINQ provides a straightforward yet expressive SQL-like syntax with which you can query an Entity Data Model and uses anonymous types to return strongly-typed results.

Using Anonymous Types to Retrieve Data
The previous example used the query output to display all the attributes of the product that matched the input criteria. However you might want to retrieve only a subset of the available columns. You can accomplish this in LINQ using the new feature named "anonymous types" introduced with C# 3.0. Essentially, anonymous types let you dynamically create a new "unknown" object without a name, to which you can then add the relevant fields as properties. Suppose you want to return only the Name and ProductNumber columns from the previous query. To accomplish this, you modify the LINQ query as follows:

   private void btnGetProductDetails_Click(object sender, 
      EventArgs e)
      string connectionString = 
      int productID = System.Convert.ToInt32(txtProductID.Text);
      using(AdventureWorks adventureWorks = new 
         var products = from prod in adventureWorks.Product  
                        where prod.ProductID == productID 
                        select new
                          ID = prod.ProductID,
                          Name = prod.Name,
                          Number = prod.ProductNumber
         foreach(var prod in products) 
Look at the select clause in the preceding example, which now reads select new. Here, the new keyword causes the query to store the results in a dynamically declared, anonymous type, which has three properties: ProductID, Name and ProductNumber.

When the compiler sees the new keyword, it dynamically creates a new type. The pseudocode for this new type might look like this:

   public class ???? 
      private string name;
      private string productNumber;
      public string Name
         get { return name; }
         set { name= value; }
      public string ProductNumber
         get { return productNumber; }
         set { productNumber = value; }
As you can see, this dynamically created class is nameless—meaning that it is an anonymous type. Here are some key advantages of using anonymous types:

Anonymous types let you create as many domain-specific representations as you need. They also obviate the need to create a fully populated data object when you only want to access a subset of its attributes, resulting in a smaller memory footprint.

Anonymous types are type-safe, meaning that they are still validated at the compile time.

Anonymous types are flexible because you can structure a class based on the data returned from a query. For example, if you have a query that goes against employee and department tables and you want to return only a subset of columns from those tables, you can use anonymous types to define an exact structure that represents the desired query results. You can accomplish all of this without having to define and instantiate a new class explicitly.

The ability to create anonymous types on the fly really brings a whole new dimension when you are working with databases. Anonymous types free you from the restrictions of pre-defined queries inherent in traditional object-relational mappers; instead, you are free to create any type of object on the fly without any restrictions.

Using "LINQ to XML" to Create Hierarchical Data
In addition to working with relational data, LINQ also provides you with a dedicated API to manipulate hierarchical XML data. This API known as "LINQ to XML" (code-named XLinq) can be very useful in converting relational data representations into hierarchical data representations and vice versa. Here's an example that shows how you can leverage XLinq to convert relational data into an XML (hierarchical) representation.

   private void btnGetCategories_Click(object sender, EventArgs e)
      string connectionString = 
      using(AdventureWorks adventureWorks = new 
         XElement categories = new XElement("Categories", 
             from category in adventureWorks.ProductSubcategory 
             new XElement("Category",
             new XAttribute("ID", category.ProductSubcategoryID),
             new XAttribute("Name", category.Name) 
The preceding code starts by creating an instance of the XElement class, which is a key object introduced with LINQ to XML. You pass the element's name to the XElement constructor as well as all the child elements. If you examine the XElement constructor, it look like this:

   public XElement(XName name, 
      params object[] content);
Because of the params keyword, you can supply a variable number of arguments (as child elements) to XElement object's constructor.

Unfortunately, the preceding code does not execute properly because of incompatibility issues between the LINQ Preview Release and the ADO.NET vNext Release, which were released at different times as CTPs. Specifically, the run-time error is caused by an incompatible System.Query assembly between these two releases. However this issue will be rectified in a future CTP release.

For more information on XLinq, please refer to my XLinq article series.

Advantages of Using LINQ to Retrieve Data
  • Using LINQ gives you the power to execute complicated queries using a simple and probably at least somewhat familiar syntax.
  • By representing entities as a set of objects in LINQ, you can work with objects that directly represent the domain model rather than only with data structures in the same format as the relational database (such as DataReaders).
  • The LINQ data access mechanism lets you create a high quality, flexible data access layer that supports compile-time checking, is easy to program, debug, and maintain.
This article discussed the role of LINQ in the ADO.NET vNext Framework and showed how to execute LINQ queries against the object services layer from your .NET client applications. Specifically, you saw the LINQ query required to retrieve data from the EDM entities via the object services layer. You have also seen the code required to filter rows and columns returned from the query results. In addition you have also understood the role of anonymous types in creating flexible .NET applications.

Thiru Thangarathinam works at Intel Corporation in Chandler, Arizona. He's a Microsoft MVP who specializes in architecting, designing, and developing distributed enterprise-class applications using .NET-related technologies. He is the author of the books "Professional ASP.NET 2.0 XML" and "Professional ASP.NET 2.0 Databases" from Wrox press and has coauthored a number of books on .NET-related technologies. He is a frequent contributor to leading technology-related online publications.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date