Skip Navigation LinksHome > Categories > Code from a Category

LINQ Joins

User Name: codelecturer
Name: Mike Chauhan
Contact Me:
Home Page:
6 years of total IT experience including programming, application development, System Maintenance . 3 years of Experienced and expertise in .Net Framework VB, Visual Basic.Net, ASP.Net 2.0, 3.5 and AD... [More]
Viewed Times: 1460
Add Date: 12/09/2012
In this article we will learn about LINQ Joins


It is common practice to normalise data, both in databases and other storage, and in objects in memory. In simple terms, normalisation is the process of extracting duplicated information from a single set of data and holding it without duplication in another set.

A key value present in both lists is used to link the information back together at a later time. For example, the stock items in a stock control system may include category information. As all of the items in the "Fresh Produce" category share the same category information, this can be extracted and held separately in a category list. The normalisation process reduces the amount of data that must be held and allows a single update to a parent item to be reflected in all of its children.

When working with databases you may achieve this normalisation by creating two tables and a foreign key relationship, often called a one-to-many or parent-child relationship. In XML you could create the category as an XML node and use child nodes for the products. When working with objects you may include a reference to a parent category in the stock item class using a property. In some cases you may have two separate collections, with one holding all categories and one holding all of the products. If there is a key property or field that can be used to match a stock item to its category, you can join the two collections using LINQ.

In this article I will demonstrate the use of joins using the Join standard query operator and the join clause of the query expression syntax. To begin, we need two sample classes to work with. The first represents a stock item with a property that will provide a link to its category:

The second class will hold the details of the categories of stock item that are available. To keep the examples simple, the class includes a Name property, which will match the category from the stock item. All stock items in the same category will also share a major category. Later we will join data of both types to create lists of objects containing both the stock item data and category and major category details.

To create a list of sample stock items, add the following code:

To complete the test data add the following code to create sample categories:

Join Standard Query Operator

In our first example we will join the two collections using the basic version of the Join standard query operator. This is an extension method of all types that support IEnumerable. It joins two lists, known as the outer and inner data, using four parameters. The first parameter supplies the inner list; the outer list is the object that the extension method is being executed against. The other three arguments accept Func delegates, each of which we will supply as a lambda expression. The three delegates are as follows:

Outer Key Selector. This delegate accepts a single argument of the type of the outer collection's items. It returns a key value, which may be of any type.

Inner Key Selector. This delegate is similar to the outer key selector. It defines how the key values are extracted from the inner collection. Where the outer and inner keys match, the data will be joined in the final results.

Result Selector. The third Func delegate defines how the results of the join will be projected. The delegate has two parameters, which will receive the outer and inner items for each matching key pair. The returned value is added to the collection returned by the Join method.

To see the Join operator in action, try executing the following code:

Here the outer collection is provided by the stock variable and the inner collection by the categories list. The first lambda expression obtains a key from each stock item by returning the Category property. The second argument creates a key for each category by returning the Name property. Wherever these two items are equal, a resultant item will be created using the third lambda. This generates an anonymously typed object containing the name and price from the stock item and the category and major category from the stock category object. The results of the operation are as follows:

Using Alternative Comparers

When the outer and inner keys are compared, the two items must match exactly for a result to be generated. If there are minor differences, for example if the keys are strings and one is upper case whilst the other is lower case, the items will not be joined. This can be overcome by using an alternative comparer. Any existing or custom comparer that implements the IEqualityComparer interface may be used.

To demonstrate, change the name of the "Vegetable" category to "vegetable". When you re-run the program you will see that the stock items in the "Vegetable" category are no longer present in the results. However, if we use a case-insensitive comparer, passed as the final argument to the Join method, these will reappear as seen in the sample below. Note that because the category name is being projected from the category object, the MinorCategory value for vegetables is returned in lower case.

Joins with Query Expression Syntax

In this final section of the article we will recreate the first example using query expression syntax. The second example has no direct equivalent as it uses an alternative comparer, which is unsupported with query syntax. To perform a join requires three new clauses, named join, on and equal.

The join clause is positioned after the from clause and the initial range variable and data source. The clause is followed by a second range variable and data source that define the second collection to be joined. The "on" clause appears next before the key selector for the first data source. Finally, the equals clause and the key selector for the second collection are added. Projection is handled as normal using a select clause.

The following sample code joins the two collections using these clauses and projects the results into an anonymous type.

Happy Programming!!!

Post a Comment

Name: (Optional)
Email: (Optional, you can get an email if somebody replys your comments)*
Email me if somebody respons my comment below:
Enter Text
as Below:
(case insensitive, if hard to read, click the "get a new one" button)
* Your email address will not be shared with any third parties for any reason.
** Maximum 1000 charactors.