Query Syntax

The use of extension methods with Lambda expression is very powerful and the previous examples have shown how these methods can be used to perform operations on data sets. However, the syntax for a more complex query is  heavily laden with function/method calls and it can be quite tricky to use. For example, suppose we want to return a list of books, published by a particular publisher and ordered by the name of the Author. The query extension method sytax for this would be:

IEnumerable<Book> faberbooks = books.Where(b => b.Publisher == "Faber & Faber").OrderBy(b => b.Author);

Some more complex queries can have an even longer chain of method calls. Query syntax provides a more natural way of expressing the requirements of a particular query, using syntax which looks like a mix of SQL and C#. The query syntax for the above example would be written:

IEnumerable<Book> faberbooks = from book in books
                               where book.Publisher == "Faber & Faber"
                               orderby book.Author
                               select book;

You can probably see that the query is expressed in a more natural way, free of a lot of the formal C# method syntax.

The basic structure of a LINQ query is that it starts with a 'from' clause and ends with either a 'select' or 'group' clause. The 'from' clause specifies the data to be queried in this case the 'books' list, using a local variable 'book' as the iterator. The 'select' specifies what to return, should the other parts of the  query return a match. It this case the query adds a copy of the particular book for each matching book.

However, there is no requirement for the 'select' clause to return data of the same type as the source data. We could equally just return  specific field values, or even a different object type derived from the content of the source data. For example, to return a list of the prices of all books by Luke Rhinehart the query would be:

IEnumerable<Double> lukesprices = from book in books
                                  where book.Author == "Luke Rhinehart"
                                  select book.Price;

Deferred Execution

One of the powerful features of Query Syntax, when used with the IEnumerable<object> return variable, is that of deferred execution. What this means is that the statement above - which returns the list of prices for Luke Rhinehart books - actually never gets executed unless you attempt to iterate through the values which would be returned.

You may ask why this is important. If you consider that a query may be potential accessing thousands of data records, amaybe even on a remote database, you don't want to have to retrieve all the records and work your way through them as that would be a waste of bandwidth, memory and processing time. Deferred execution allows the actual execution to take place in a more sensible way, for example, if the query is to an SQL database the query can be sent to the DBMS and executed there, thus only returning the required object, and only when the data is actually required.

There are two special methods of IEnumerable which force the execution of a query. These are ToArray() and ToList(). For example, to retrieve an array of prices of Luke Rhinehart books we can use the following statement:

Array<Double> lukesprices = (from book in books
                                  where book.Author == "Luke Rhinehart"
                                  select book.Price).ToArray();

Valid XHTML 1.0! | Valid CSS! | WCAG Approved AA
Page design by: John P Scott - Hosting with: Netcetera