Many of my course attendees, book readers, and attendees of my conference sessions know my Formula 1 samples This time in a workshop I had questions on how to do some specific queries where the Formula 1 champions again come very handy.
Using the Racer class that has properties as shown here:
public string FirstName { get; set; } public string LastName { get; set; } public string Country { get; set; } public int Wins { get; set; } public int Starts { get; set; } public int[] Years { get; private set; } public string[] Cars { get; private set; }
these questions were asked: “how to get champions from three specific years”, and “how to sort the champions based on the first year they won the championship”. The interesting part is here that the Year property of a Racer is a collection on itself. A racer can be a champion in several years. Still, this can be done easily with LINQ.
The first example I’ve done more general instead of giving the option for three years, the method declaration allows for a flexible number of years:
public static void ChampionsOfSeveralYears(params int[] years)
And it can be invoked like this:
ChampionsOfSeveralYears(1970, 1975, 1984);
The query is not difficult to do. A compound from is good to access all the years of a racer, then the year can be used with the Contains method to check if the year of a racer is within the collection of years received with the parameter of the method:
var q = from r in Formula1.GetChampions() from y in r.Years where years.Contains(y) select r;
If you are curious, the result passing the years shown earlier is
Jochen Rindt Niki Lauda Niki Lauda
If the matching year should be shown with the racer, this can be done by creating a new type:
var q = from r in Formula1.GetChampions() from y in r.Years where years.Contains(y) select new { Racer = r, Year = y };
To get the first year of a racers championship the operator First comes handy. This sample has several orderby. Years.OrderBy(y => y) is first used to order the championship years of a single racer in case this is not already ordered. Then the first of these years is used, and then the result with all the racers and their first championship year is ordered.
var q = from r in Formula1.GetChampions() orderby r.Years.OrderBy(y => y).First() select r;
Many more queries are found in the book Professional C# 4 with .NET 4 and in my LINQ workshops.
Also more LINQ queries here:
- LINQ Compound From with C# and Visual Basic
- LINQ Grouping with C# and Visual Basic
- LINQ with .NET 4 – Zip
- LINQ with joins
- Custom Extension Methods
- What’s behind a Query Expression
- Filtering and Sorting XML
- Filtering and Sorting Data from the Database
- Filtering and Sorting Object Lists
Christian
But if you a full normalized database, then the Years property is a foreign key to a table:
public Racer Champion {get; set;}
public int Year {get; set;}
Then our query could be:
from y in YearChampions
where years.Contains(y.Year)
select y.Champion;
Posted by: James C | 12/09/2010 at 10:29 PM
Yes, if it's a normalized database. In the sample here it's just linq to objects with a simple collection of Racer objects :-)
Posted by: Christian | 12/10/2010 at 06:28 PM