Standard Query Operators


Where, OrderByDescending, and Select are only few of the query operators by LINQ. The LINQ query defines a declarative syntax for the most common operators. There are many more standard query operators available.

The following table lists the standard query operators defined by LINQ.

Open table as spreadsheet

Standard Query Operators

Description

Where

The Where query operator defines a restriction to filter the collection.

Select

SelectMany

Select and SelectMany define a projection to select values of the result based on a selector function.

OrderBy

ThenBy

OrderByDescending

ThenByDescending

Reverse

These operators are used for sorting. OrderBy sorts values in ascending order, OrderByDescending in descending order. ThenBy and ThenByDescending operators are used for a secondary sort if the first sort gives similar results. Reverse reverses the elements in the collection.

Join

GroupJoin

With the Join operator a join of two collections can be done. This is similar to the JOIN you know from SQL.

GroupBy

The GroupBy operator groups elements with a common key.

Any

All

Contains

Any, All, and Contains are quantifier operators. Any determines if any element in the collection satisfies a predicate function; All determines if all elements in the collection satisfy a predicate. Contains checks whether a specific element is in the collection.

Take

Skip

TakeWhile

SkipWhile

Take, Skip, TakeWhile, and SkipWhile are partitioning operators. With these, you get a partial result. With Take, you have to specify the number of elements to take from the collection; Skip ignores the specified number of elements and takes the rest. TakeWhile takes the elements as long as a condition is true.

Distinct

Union

Intersect

Except

Set operators return a collection set. Distinct removes duplicates from a collection. With the exception of Distinct, the other set operators require two collections. Union returns unique elements that appear in either of the two collections. Intersect returns elements that appear in both collections. Except returns elements that appear in just one collection.

First

FirstOrDefault

Last

LastOrDefault

ElementAt

ElementAtOrDefault

Single

SingleOrDefault

Element operators just return one element. First returns the first element that satisfies a condition. FirstOrDefault is similar to First, but it returns a default value of the type if the element is not found. Last returns the last element that satisfies a condition. With ElementAt, you specify the position of the element to return. Single returns the only one element that satisfies a condition. If more than one element satisfies the condition, an exception is thrown.

Count

Sum

Min

Max

Average

Aggregate

With aggregate operators, you can get the sum of all values, the number of all elements, the element with the lowest or highest value, an average number, and so on.

ToArray

ToEnumerable

ToList

ToDictionary

OfType<T>

Conversion operators convert the collection to an array, IEnumerable, IList, Idictionary, and so on.

Empty

Range

Repeat

Generation operators return a new collection. The collection is empty; with the Empty operator, Range returns a sequence of numbers, and Repeat returns a collection with one repeated value.

Let’s have a look at some examples for a query.

With the Where operator, you can combine multiple expressions, for example, only get the racers from England that won more than six races:

  var britishRacers = from r in Formula1.GetRacers()                     where r.Country == "England" && r.Wins > 6                     orderby r.Wins descending                     select r; 

Iterating through the result, you get these English racers that won more than six races:

 Nigel Mansell Damon Hill Graham Hill James Hunt

Now, it would be interesting how many racers are from what country. To get this information, you can use group by with the LINQ query. group r by r.Country groups the racers by the country. The group by expression is using the GroupBy method that returns an object that implements the IGrouping<T> interface. IGrouping<K, T> inherits from IEnumerable<T> and offers an additional property Key that is used with the select that follows to return the key as Country property. The Count property returned is using the Count() extension method to get the number of elements within a group.

  var countryCounts = from r in Formula1.GetRacers()                     group r by r.Country into g                     orderby g.Count() descending                     select new { Country = g.Key, Count = g.Count() }; foreach (var t in titleCounts) {    Console.WriteLine(t.Country + " " + t.Count); } 

Tip 

The new operator followed by the curly brackets is a new C# 3.0 operator to create an anonymous type. This is discussed later in this chapter.

In the result, you can see how many champions are from which country:

 Italy 2 Argentina 1 England 6 USA 2 Scotland 2 Australia 2 New Zealand 1 Austria 2 Brazil 3 South Africa 1 Finland 2 France 1 Canada 1 Germany 1 Spain 1

The result is not sorted. With orderby you can sort the collection. You can add orderby before doing the grouping, so all countries are sorted before they are grouped. Here, the result is sorted as well grouped by the country:

 var countryCounts = from r in Formula1.GetRacers()                     orderby r.Country                     group r by r.Country into g                     select new { Country = g.Key, Count = g.Count() };

With the previous sort, it is not possible to sort the countries by the number of champions from the country. Placing orderby after the group sorts the result. With orderby after the grouping, you can access the group element for ordering. Here, the order is done first by the count and then by the country that is the Key of the IGrouping<K, T> interface. The list is first ordered by the number of racers in each country in descending order, and if the number of racers is the same among multiple countries, the listings are ordered by country in ascending order.

 var countryCounts = from r in Formula1.GetRacers()                     group r by r.Country into g                                         orderby g.Count() descending, g.Key                     select new { Country = g.Key, Count = g.Count() };

With the LINQ query expression, you can add several values separated by commas to the orderby expression. The extension methods behind this are OrderBy() for the first element and ThenBy() for the elements that follow.

The result is a sorted list:

 England 6 Brazil 3 Australia 2 Austria 2 Finland 2 Italy 2 Scotland 2 USA 2 Argentina 1 Canada 1 France 1 Germany 1 New Zealand 1 South Africa 1 Spain 1

If you do not want to return all the elements, but just would like to return the first three from the results, you can add the Take() extension method to the result:

 var countryCounts = (from r in Formula1.GetRacers()                      group r by r.Country into g                      orderby g.Count() descending, g.Key                      select new { Country = g.Key, Count = g.Count() }).                          Take(3); 

In the result, now only three countries are shown:

 England 6 Brazil 3 Australia 2

To get just one racer, with the highest number of wins, the collection is sorted by the number of wins, and just the first element returned:

  var champion = (from r in Formula1.GetRacers()                 orderby r.Wins descending                 select new { Firstname = r.Firstname, Lastname = r.Lastname }).                 First(); Console.WriteLine(champion.Firstname + " " + champion.Lastname); 

Michael Schumacher is the racer who has won the greatest number of races, as shown in the result:

 Michael Schumacher

To find out which racers won the most races in relation to the number of races driven, a calculation can be added to the orderby expression. The calculation is also added to the selection to return the calculation with the new objects returned. After the collection is sorted, the first seven racers in the list are taken.

  var winRelation = (from r in Formula1.GetRacers()                    orderby ((float)r.Starts / r.Wins)                    select new { Name=r.Firstname + " " + r.Lastname,                                 WinRelation = (float)r.Starts / r.Wins}).                       Take(7); foreach (var r in winRelation) {    Console.WriteLine("{0}, {1:#.##}", r.Name, r.WinRelation); } 

In the result, you can see the racers that won the most races in regard to races driven. Juan Manual Fangio nearly won every second race.

 Juan Manuel Fangio, 2.13 Michal Schumacher, 2.75 Jim Clark, 2.88 Alberto Ascari, 3.2 Jackie Stewart, 3.67 Alain Prost, 3.86 Ayrton Senna, 3.93

If you do the same query as before, now with extension methods, the query looks as follows. Instead of using the orderby and select expressions, the extension methods OrderBy() and Select() are used here:

 var winRelation = Formula1.GetRacers().    OrderBy<Racer, float>(r => (float)r.Starts / r.Wins).    Select(r => new { Name = r.Firstname + " " + r.Lastname,                      WinRelation = (float)r.Starts / r.Wins }).    Take(7); foreach (var r in winRelation) {    Console.WriteLine("{0}, {1:#.##}", r.Name, r.WinRelation); }

Now let’s have a look to the parameter of the extension method r => (float)r.Starts / r.Wins. This is a lambda expression.




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net