FREE BOOK

Chapter 11: An introduction to LINQ

Posted by Murach Free Book | LINQ August 13, 2009
In this chapter, you’ll learn the basic concepts and skills for using a new feature of C# 2008 called LINQ. To illustrate these concepts and skills, I’ll use an implementation of LINQ called LINQ to Objects. You use LINQ to Objects to work with in-memory data structures such as generic lists and arrays.

How to code query expressions

Now that you have a basic understanding of what a LINQ query is, you need to learn the syntax for coding query expressions. That's what you'll learn
in the topics that follow.

How to identify the data source for a query

To identify the source of data for a query, you use the from clause shown in figure 11-4. As you can see, this clause declares a range variable that will be used to represent each element of the data source, and it names the data source, which must be an enumerable type. Note that because the result of a query is an enumerable type, the data source can be a previously declared query variable. The from clause can also declare a type for the range variable, although the type is usually omitted. If it is omitted, it's determined by the type of elements in the data source.

The example in this figure shows how to use the from clause with a generic list of invoices. The first statement in this example creates a list that's based on the Invoice class and loads invoices into it using the GetInvoices method of the InvoiceDB class. Note that the Invoice class used in this example and other examples in this chapter is identical to the class presented in figure 6-7 of chapter 6, except that it doesn't include a BalanceDue method. Also note that it's not important for you to know how the GetInvoices method of the InvoiceDB class works. All you need to know is that this method returns a List<Invoice> object. This object is then assigned to a variable named invoiceList.

The second statement defines the query expression, which consists of just the from clause and a select clause. The from clause uses the name invoice for the range variable, and it identifies invoiceList as the data source. This expression is then stored in a query variable named invoices. Finally, the code that follows uses a foreach statement to loop through the invoices and calculate a sum of the InvoiceTotal field for each invoice.

At this point, you should realize that a query expression must always start with a from clause that identifies the data source. That way, C# knows what the source of data for the query is, and it can help you construct the rest of the query based on that data source. In addition, a query expression must end with either a select clause or a group clause. In the example in this figure, the select clause simply indicates that Invoice objects should be returned by the query. Later in this chapter, however, you'll see that you can use the select clause to return just the fields you want from each element of a data source.

You may have noticed in this example that the variable that's used in the query expression and the variable that's used in the foreach loop have the same name. That makes sense because they both refer to an element in the data source. However, you should know that you don't have to use the same names for these variables. In fact, when you code more sophisticated query expressions, you'll want to use different variable names to indicate the differences between the elements they refer to. That'll make more sense when you see the group clause later in this chapter.

The syntax of the from clause

from [type] elementName in collectionName

A LINQ query that includes just a From clause

A statement that declares and populates a generic list of invoices
List<Invoice> invoiceList = InvoiceDB.GetInvoices();

A statement that defines the query expression

var invoices = from invoice in invoiceList

               select invoice;

Code that executes the query

decimal sum = 0;

foreach (var invoice in invoiceList)

{

    sum += invoice.InvoiceTotal;

}

MessageBox.Show(sum.ToString("c"), "Sum of Invoices");

The resulting dialog box

Description

  • The from clause identifies the source of data for a query and declares a range variable that's used to iterate through the elements of the data source.
  • If the range variable you use in a query expression and the range variable you use in the foreach statement that executes the query refer to the same type of elements, you should give them the same name for clarity. Otherwise, you should give them different names to indicate the type of elements they refer to.
  • The From clause must be the first clause in a query expression. In addition, a query expression must end with a select clause or a group clause.

Figure 11-4 How to identify the data source for a query

How to filter the results of a query

To filter the results of a query, you use the where clause shown in figure 11-5. On this clause, you specify a condition that an element must meet to be returned by the query. The condition is coded as a Boolean expression. The example in this figure illustrates how this works.

The where clause in this example specifies that for an element to be returned from the generic list of invoices, the invoice's balance due, which is calculated by subtracting its PaymentTotal and CreditTotal columns from its InvoiceTotal column, must be greater than zero. In addition, the due date must be less than 15 days from the current date. Notice here that the range variable that's declared by the from clause is used in the where clause to refer to each Invoice object. Then, the foreach statement that executes the query refers to the VendorID, InvoiceNumber, InvoiceTotal, PaymentTotal, and CreditTotal properties of each Invoice object that's returned by the query to create a string that's displayed in a message box.

The syntax of the where clause
where condition

A LINQ query that filters the generic list of invoices

A query expression that returns invoices with a balance due within the next 15 days

var invoices = from invoice in invoiceList

               where invoice.InvoiceTotal

               - invoice.PaymentTotal

               - invoice.CreditTotal > 0

               && invoice.DueDate < DateTime.Today.AddDays(15)

               select invoice;

Code that executes the query

string invoiceDisplay = "Vendor ID\tInvoice No.\tBalance Due\n";

foreach (var invoice in invoices)

{

    invoiceDisplay += invoice.VendorID + "\t\t" +

    invoice.InvoiceNumber + "\t";

    if (invoice.InvoiceNumber.Length < 8)

        invoiceDisplay += "\t";

    invoiceDisplay += (invoice.InvoiceTotal - invoice.PaymentTotal

    - invoice.CreditTotal).ToString("c") + "\n";

}

MessageBox.Show(invoiceDisplay, "Vendor Invoices Due");

The resulting dialog box

Description

  • The where clause lets you filter the data in a data source by specifying a condition that the elements of the data source must meet to be returned by the query.
  • The condition is coded as a Boolean expression that can contain one or more relational and logical operators.

Figure 11-5 How to filter the results of a query

Total Pages : 10 12345

comments