Appendix J
LINQ

This appendix provides syntax summaries for the most useful LINQ methods. For more detailed information, see Chapter 8, “LINQ.”

Basic LINQ Query Syntax

The following text shows the typical syntax for a LINQ query.

from ... where ... orderby ... select ...

The following sections describe these four standard clauses. The sections after those describe some of the other most useful LINQ clauses.

from

The from clause tells where the data comes from and defines the name by which it is known within the LINQ query.

from queryVariable in dataSource

Examples:

var customerQuery =
    from person in customers
    select person;
var scoresQuery =
    from student in students
    from score in testScores
    where student.StudentId == score.StudentId
    select new {student, score};

Usually, if you select data from multiple sources, you will want to use a where clause to join the results from the sources.

where

The where clause applies filters to the records selected by the from clause. The syntax follows.

where conditions

Use comparison operators (>, <, and ==), logical operators (!, |, and &&), object methods (ToString and Length), and functions to build complex conditions.

For example, the following query selects student and test score data, matching students to their test scores.

var scoresQuery =
    from student in students
    from score in testScores
    where student.StudentId == score.StudentId
    select new {student, score};

The following example selects students with last names starting with S.

var scoresQuery =
    from student in students
    from score in testScores
    where student.StudentId == score.StudentId
          && student.LastName.StartsWith("S")
    select new {student, score};

orderby

The orderby clause makes a query sort the selected objects. For example, the following query selects students and their scores ordered by student last name followed by first name.

var scoresQuery =
    from student in students
    from score in testScores
    where student.StudentId == score.StudentId
    orderby student.LastName, student.FirstName
    select new {student, score};

Add the descending keyword to sort a field in descending order.

select

The select clause lists the fields that the query should select into its result. Optionally, you can add an alias to the result.

The following query selects the customers’ FirstName and LastName values concatenated and gives the result the alias Name.

var customerQuery = from person in customers
    select Name = person.FirstName + " " + person.LastName;

You can pass values from the data sources into functions or constructors. For example, suppose the Person class has a constructor that takes first and last names as parameters. Then the following query returns a group of Person objects created from the selected customer data.

var customerQuery = from person in customers
    select new Person(person.FirstName, person.LastName);

join

The join keyword selects data from multiple data sources matching up corresponding fields. The following pseudo-code shows the join command’s syntax.

from variable1 in dataSource1
join variable2 in dataSource2
  on variable1.field1 equals variable2.field2

For example, the following query selects Customer objects from the customers array. For each Customer object, it selects Order objects from the orders array where the two records have the same CustomerId value.

var query =
    from customer in customers
    join order in orders
    on customer.CustomerId equals order.CustomerId
    select new { customer, order };

Note that you can get a similar result by using a where clause. The following query selects a similar set of objects without using the join keyword.

var query =
    from customer in customers
    from order in orders
    where customer.CustomerId == order.CustomerId
    select new { customer, order };

group by

The group by clause lets a program select data from a flat, relational style format and build a hierarchical arrangement of objects. The following code shows a simple example.

var query =
    from order in orders
    group order by order.CustomerId;

This query selects Order objects from the orders array and groups the selected objects by their CustomerId values.

The result is a list of objects representing the groups. Each of those objects has a Key property that gives the value that was used to build that group. In this example, the Key is the value of the objects’ CustomerId values.

Each of the group objects is also enumerable, so the program can loop through the objects that are in its group.

Aggregate Values

When you group data, you can use aggregate methods to select combined values from the groups.

The following query selects orders grouped by CustomerId. The Sum aggregate method highlighted in bold selects the sum of the prices of the orders in each group.

var query =
    from order in orders
    group order by order.CustomerId into Orders
    select new
    {
        ID = Orders.Key,
        Orders,
        TotalPrice = Orders.Sum(order => order.Price)
    };

Limiting Results

The following list summarizes methods that LINQ provides for limiting the results returned by a query.

  • First—Returns the first result and discards the rest. If the result includes no values, this throws an exception.
  • FirstOrDefault—Returns the first result and discards the rest. If the query contains no results, it returns a default value.
  • Last—Returns the last result and discards the rest. If the result includes no values, this throws an exception.
  • LastOrDefault—Returns the last result and discards the rest. If the query contains no results, it returns a default value.
  • Single—Returns the single item selected by the query. If the query does not contain exactly one result, this throws an exception.
  • SingleOrDefault—Returns the single item selected by the query. If the query contains no results, this returns a default value. If the query contains more than one item, this throws an exception.
  • Skip—Discards a specified number of results and keeps the rest.
  • SkipWhile—Discards results as long as some condition is true and then keeps the rest. (The condition is given by a method, often a lambda expression.)
  • Take—Keeps a specified number of results and discards the rest.
  • TakeWhile—Keeps results as long as some condition is true and then discards the rest.

LINQ Functions

The following table summarizes LINQ useful extension methods that are not available from C# LINQ query syntax.

FunctionPurpose
AggregateUses a function specified by the code to calculate a custom aggregate
ConcatConcatenates two sequences into a new sequence
ContainsReturns true if the result contains a specific value
DefaultIfEmptyReturns the query’s result or a default value if the query returns an empty result
ElementAtReturns an element at a specific position in the query’s result
ElementAtOrDefaultReturns an element at a specific position in the query’s result or a default value if there is no such position
EmptyCreates an empty IEnumerable
ExceptReturns the items in one IEnumerable that are not in a second IEnumerable
IntersectionReturns the intersection of two IEnumerable objects
RangeCreates an IEnumerable containing a range of integer values
RepeatCreates an IEnumerable containing a value repeated a specific number of times
SequenceEqualReturns true if two sequences are identical
UnionReturns the union of two IEnumerable objects

The following table summarizes LINQ data type conversion methods.

FunctionPurpose
AsEnumerableConverts the result to IEnumerable<T>
AsQueryableConverts an IEnumerable to IQueryable
OfTypeRemoves items that cannot be cast into a specific type
ToArrayPlaces the results in an array
ToDictionaryPlaces the results in a Dictionary
ToListConverts the result to List<T>
ToLookupPlaces the results in a Lookup (one-to-many dictionary)

LINQ to XML

The following sections describe LINQ methods to move data in and out of XML.

XML Literals

C# does not support XML literals, but you can pass a string containing XML data into an XML object’s Parse method, as shown in the following code.

XElement xelement = XElement.Parse(
@"<Employees>
    <Employee FirstName=""Ann"" LastName=""Archer""/>
    <Employee FirstName='Ben' LastName='Baker'/>
    <Employee>
      <FirstName>Cindy</FirstName>
      <LastName>Cant</LastName>
    </Employee>
  </Employees>
");

LINQ into XML

LINQ’s XML classes provide constructors that enable you to build XML documents relatively easily. Each constructor’s parameter list ends with a parameter array, so you can pass any number of items into it. The following code uses functional construction to build an XML structure.

XElement employees = new XElement("Employees",
    new XElement("Employee",
        new XAttribute("FirstName", "Ann"),
        new XAttribute("LastName", "Archer")
    ),
    new XElement("Employee",
        new XAttribute("FirstName", "Ben"),
        new XAttribute("LastName", "Baker")
    ),
    new XElement("Employee",
        new XElement("FirstName", "Cindy"),
        new XElement("LastName", "Cant")
    )
);

LINQ out of XML

XML classes such as XElement provide LINQ functions that enable you to use LINQ queries on them just as you can select data from IEnumerable objects.

The following code searches the XElement named document for descendants named "Employee" and selects their FirstName and LastName attributes.

var selectEmployee =
    from employee in document.Descendants("Employee")
    select new
    {
        FirstName = employee.Attribute("FirstName").Value,
        LastName = employee.Attribute("LastName").Value
    };

The following table describes other methods supported by XElement that a program can use to navigate through an XML hierarchy. Most of the functions return IEnumerable objects that you can use in LINQ queries.

FunctionReturns
AncestorsIEnumerable containing all ancestors of the element.
AncestorsAndSelfIEnumerable containing this element followed by all its ancestors.
AttributeThe element’s attribute with a specific name.
AttributesIEnumerable containing the element’s attributes.
DescendantsIEnumerable containing all descendants of the element.
DescendantsAndSelfIEnumerable containing this element followed by all its descendants.
DescendantNodesIEnumerable containing all descendant nodes of the element. These include all nodes such as XElement and XText.
DescendantNodesAndSelfIEnumerable containing this element followed by all its descendant nodes.
ElementThe first child element with a specific name.
ElementsIEnumerable containing the immediate children of the element.
ElementsAfterSelfIEnumerable containing the siblings of the element that come after this element.
ElementsBeforeSelfIEnumerable containing the siblings of the element that come before this element.
NodesIEnumerable containing the nodes that are immediate children of the element. These include all nodes such as XElement and XText.
NodesAfterSelfIEnumerable containing the sibling nodes of the element that come after this element.
NodesBeforeSelfIEnumerable containing the sibling nodes of the element that come before this element.

LINQ to ADO.NET

LINQ to ADO.NET provides tools that enable you to apply LINQ-style queries to objects used by ADO.NET to store and interact with relational data. LINQ to ADO.NET includes three components: LINQ to SQL, LINQ to Entities, and LINQ to DataSet.

Building and managing SQL Server databases and the Entity Framework are topics too large to cover in this book, so LINQ to SQL and LINQ to Entities are not described in more detail here. For more information, consult the online help or Microsoft’s website.

LINQ to DataSet lets a program use LINQ-style queries to select data from DataSet objects.

For example, suppose the testScoresDataSet object contains tables named Students and TestScores. Then the following code gets references to the DataTable objects that represent the tables.

DataTable studentsTable = testScoresDataSet.Tables["Students"];
DataTable scoresTable = testScoresDataSet.Tables["TestScores"];

You can then use LINQ to query the DataTable table objects. For example, the following code selects the names of students with LastName before "F" alphabetically.

var namesBeforeFQuery =
    from student in studentsTable.AsEnumerable()
    where (student.Field<string>("LastName").CompareTo("F") < 0)
    orderby student.Field<string>("LastName")
    select new
    {
        FirstName = student.Field<string>("FirstName"),
        LastName = student.Field<string>("LastName")
    };
namesBeforeDDataGrid.DataSource = namesBeforeFQuery.ToList();

The following list summarizes the key differences between a LINQ to DataSet query and a normal LINQ to Objects query.

  • The LINQ to DataSet query must use the DataTable object’s AsEnumerable method to make the object queryable.
  • The code can access the fields in a DataRow, as in student.Field<string>("LastName").
  • If you want to display the results in a bound control such as a DataGrid or ListBox, use the query’s ToList method.

PLINQ

Adding parallelism to LINQ is remarkably simple. First, add a reference to the System.Threading library to your program. Then add a call to AsParallel to the enumerable object that you’re searching. For example, the following code uses AsParallel to select the even numbers from the array numbers.

var evens =
    from int number in numbers.AsParallel()
    where number % 2 == 0
    select number;
    join order in orders on customer.CustomerId equals order.CustomerId
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.229.161