LINQ (implicit and lambda expressions)

Source: Internet
Author: User

A groundbreaking innovation in. NET is (Language Integrated Query), This language extension allows you to execute queries without having to leave the comfortable C # language.

       LINQ defines the keywords used to build the query expression. These query expressions can select, filter, sort, group, and convert data. With various LINQ extensions, you can use the same query expression for different data sources.

Although you can use LINQ anywhere, only ASP. NET applications are most likely to use it as part of database components. You can use LINQ together with the ADO. NET data access code, or replace the ADO. NET data access code with the help of LINQ to Entities.

 

Basics

This is the simplest way to get to know how it works for a memory set. This is the most simple form of LINQ to Objects.

 

In essence, LINQ to Objects can replace logic with declarative LINQ expressions (such as foreach blocks ):

EmployeeDB db = new EmployeeDB ();
Protected void btnForeach_Click (object sender, EventArgs e)
{
List <EmployeeDetails> employees = db. GetEmployees ();
List <EmployeeDetails> matches = new List <EmployeeDetails> ();
Foreach (EmployeeDetails employee in employees)
    {
If (employee. LastName. StartsWith ("D "))
        {
Matches. Add (employee );
        }
    }
GridEmployees. DataSource = matches;
GridEmployees. DataBind ();
}
 
Protected void btnLINQ_Click (object sender, EventArgs e)
{
List <EmployeeDetails> employees = db. GetEmployees ();
IEnumerable <EmployeeDetails> matches;
Matches = from employee in employees
Where employee. LastName. StartsWith ("D ")
Select employee;
GridEmployees. DataSource = matches;
GridEmployees. DataBind ();
}

 

Delayed execution

A major difference between the code using foreach blocks and the code using a LINQ expression is that they process matching set types. For foreach, the matched set is created as a set of specific types (strong type List <T>). In The LINQ example, the matched set is exposed only through the IEnumerable <T> interface implemented by it.

This difference is caused by the use of delayed execution in LINQ. It may be different from what you expected. The matching object is not an intuitive set containing the matching EmployeeDetails object, but a special LINQ object that can capture data when you need it.

       Depending on the query expression, the LINQ expression can return different objects, such as WhereListIterator, UnionIterator, and SelectIterator, because the IEnumerable <T> interface interacts with the result, you do not need to know the specific iteration class used by the code.

 

How does LINQ work?
  • To use LINQ, you must create a LINQ expression.
  • The return value of a LINQ expression is an iterator object that implements IEnumerable <T>.
  • When an iterator object is enumerated, LINQ executes its work.

Q: How does LINQ execute expressions? What does it do to generate a filter result?

A: The data types you query vary. LINQ to Entities converts a LINQ expression to a database command. Therefore, you need to open a database connection and execute a database query to obtain the data you requested. In the previous example, if you use LINQ to Objects, the process of executing the LINQ statement will be much simpler. In fact, at this time, only a foreach loop is used to traverse the set from start to end.

 

LINQ expressions

Although the order of clauses is adjusted again, the LINQ expression is quite similar to the SQL query on the surface.

       All LINQ expressions must have a from clause for the specified data source and a select clause for the data to be obtained (or a group clause that defines the data to be put into a group ).

The from clause must be placed at the beginning, and the from clause determines the information of the two parts. The word table following in indicates the data source, and the word following from provides a kana for each individual in the data source:

Matches = from employee in employees

The following is a simple LINQ query that retrieves all data from the employees collection:

Matches = from employee in employees
Select employee;

Tip:

Examples of expressions can be found in Microsoft's 101 LINQ example (http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b.

 

1. Projection

You can modify the select clause to obtain a group of data.

// Sample 1
IEnumerable <string> matches;
Matches = from employee in employees
Select employee. FirstName;
 
// Sample 2
IEnumerable <string> matches;
Matches = from employee in employees
Select employee. FirstName + employee. LastName;

 

When selecting information, you can use the standard C # operator alignment to modify numeric or string data.More interestingly, a new class can be dynamically defined to encapsulate the returned information. C # The anonymous class can do this by adding a new keyword to the select clause and assigning the selected content to the attribute in the form of an object:

Var matches = from employee in employees
Select new {First = employee. FirstName, Last = employee. LastName };

       This expression returns a group of implicitly created class objects during execution. You will not see the definition of the class and cannot pass the instance to the method call, because it is generated by the compiler and has a meaningless name automatically created. However, you can use this class locally, access the First and Last attributes, or even use it with data binding (ASP. NET uses reflection to obtain the corresponding value based on the attribute name ).

       The ability to convert the data being queried into various structures is called projection.

When referencing an independent object, you must also use the keyword var, such as performing iteration on the previous result:

Foreach (VarEmployee in matches)
{
// Read First and Last
}

 

Of course, when executing projection, it is not only possible to use anonymous classes. You can formally define the type and use it in the expression:

Public class EmployeeName
{
Public string FirstName {get; set ;}
Public string LastName {get; set ;}
 
Public EmployeeName (string firstName, string lastName)
    {
This. FirstName = firstName;
This. LastName = lastName;
    }
}
 
IEnumerable <EmployeeName> matches = from employee in employees
Select new EmployeeName {FirstName = employee. FirstName,
LastName = employee. LastName };

       The expression above works because the FirstName and LastName attributes can be publicly accessed and are not read-only.After the EmployeeName object is created, LINQ sets these attributes. In addition, you can also provide other parameters for the parameterized constructor in the brackets behind the EmployeeName class name:

IEnumerable <EmployeeName> matches = from employee in employees
Select new EmployeeName (employee. FirstName, employee. LastName );

 

 

2. Filtering and sorting

IEnumerable <EmployeeDetails> matches;
Matches = from employee in employees
Where employee. LastName. StartsWith ("D ")
Select employee;

The where clause accepts a condition expression, which is calculated for each project. If the result is true, the project is included in the result. However, LINQ uses the same delayed execution model, that is, it does not calculate the where clause until the result set is iterated.

 

As you may have guessed, you can use logic and (&) and logic or (|) operators combine multiple conditional expressions and can use relational operators (such as <, <=,>,> = ):

IEnumerable <Product> matches;
Matches = from product in products
Where product. UnitsInStock> 0 & product. UnitPrice> 3.00
Select product;

 

An interesting feature of a LINQ expression is that it allows you to call your own methods at any time. For example, you can create a function TestEmployee () for checking employees and return true or false based on whether it is in the result set:

Private bool TestEmployee (EmployeeDetails employee)
{
Return employee. LastName. StartsWith ("D ");
}

Then, you can use:

IEnumerable <EmployeeDetails> matches;
Matches = from employee in employees
Where TestEmployee (employee)
Select employee;

 

The orderby operator is also intuitive. Its model is based on the query statements in SQL. You only need to provide one or more values separated by commas (,) for sorting (you can add decending in descending order ):

IEnumerable <EmployeeDetails> matches;
Matches = from employee in employees
Orderby employee. LastName, employee. FirstName
Select employee;

Note:

       All types that implement IComparable support sorting. It is one of the core data types of. NET (such as values, dates, and strings ). You can also pass a custom IComparable object to sort data.

 

3. Grouping and aggregation

Grouping allows you to concentrate a large amount of information into a simplified summary.

       Grouping is a projection because the objects in the result set are different from those in the data source set.For example, assume that you are processing a set of Product objects and decide to put them in a specific price Group. The final result is the IEnumerable <T> set of grouping objects. Each object represents a specific product in a price range.Each group implements the IGrouping <T, K> interface of the System. Linq namespace.

To use a group, you must first make two decisions:

  • Conditions for creating a group
  • What information is displayed for each group?

The first task is relatively simple. Use the group, by, and into keywords to select the objects to be grouped, determine how to group and determine the kana to be used when referencing each group:

Var matches = from employee in employees
Group employee by employee. TitleOfCourtesy into g
...
// Using g as a group name in LINQ is a common convention.

 

Objects with the same data are stored in the same group. To group data by value range, you need to write a piece of computing code to generate the same value for each group. For example, you need to group products by 50 RMB for each price range:

Var matches = from product in products
Group product by (int) (product. UnitPrice/50) into g
...

Currently, the group keys for all products with prices less than 50 RMB are 0, while those with prices between 50-100 are 1, and so on.

       After obtaining the group, you must determine the information returned by the group results. Each group is exposed to code as an object that implements the IGrouping <T, K> interface. For example, the previous expression creates a group of the IGrouping <int, Product> type. That is to say, the key-value type of the group is integer, and the element type is Product.

The IGrouping <T, K> interface only provides one attribute Key, which is used to return the value of the created group. For example, to create a list of TitleOfCourtesy strings that display each TitleOfCourtesy group, use the following expression:

Var matches = from emp in employees
Group emp by emp. TitleOfCourtesy into g
Select g. Key;

Tip:

For this example, you can also use IEnumerable <string> to replace the var keyword, because the final result is a series of strings. Then, the var keyword is usually used in grouping queries, because projection and anonymous classes are usually used to obtain more useful summary information.

 

You can also return the entire group:

Var matches = from emp in employees
Group emp by emp. TitleOfCourtesy into g
Select g;

       This is useless for data binding. Because ASP. NET cannot display any useful information about each group. However, it allows you to easily iterate data in each group:

Foreach (IGrouping <string, EmployeeDetails> group in matches)
{
Foreach (EmployeeDetails emp in group)
    {
// Do something
    }
}

This code shows that even if a group is created, each project in the group can be accessed flexibly.

 

From a more practical perspective, you can use aggregate functions to calculate data in a group. The LINQ aggregate function imitates database aggregate functions that may have been used in the past. It allows technology and summarization of elements in the group to obtain the minimum, maximum, and average values.

The following example returns an anonymous type that contains the key values of the group and the number of objects in the group. An embedded method is used to Count ():

Var matches = from emp in employees
Group emp by emp. TitleOfCourtesy into g
Select new {Title = g. Key, Employees = g. Count ()};

 

One thing to note in the previous example is that it uses an extension method. Essentially, extension methods are a core set of functions of LINQ. They need to be called directly instead of using special C # operators.

The difference between an extension method and a common method is that the extension method is not defined in the class using this method. LINQ has a System. Linq. Enumerable class that defines dozens of extension methods that can be called by all objects that implement IEnumerable <T>.

In addition to Count (), LINQ also defines a large number of powerful extension methods that can be applied in groups, such as the aggregate functions Max (), Min (), and Average. The LINQ expressions that use these methods are more complex, because they also use another C # feature called lambda expressions, which allows other parameters for the extension method. For Max (), Min (), and Average (), lambda expressions allow you to specify attributes for calculation.

This example is used to calculate the maximum price, minimum price, and average price of each item in each category:

Var categories = from p in products
Group p by p. Category into g
Select new
                 {
Category = g. Key,
MaxPrice = g. Max (p => p. UnitPrice ),
MinPrice = g. Min (p => p. UnitPrice ),
Avuplice = g. Average (p => p. UnitPrice)
};

 

Reveal the details of the LINQ expression

Although LINQ uses new C # keywords (such as from, in, and select), the implementation of these keywords is provided by other classes. Actually,All LINQ queries are converted into calls of a group of methods. In addition to conversions, you can also directly call these methods:

Var matches = from emp in employees
Select emp;
 
// The above expression can be rewritten as follows:
Var matches = employees. Select (employee => employee );

The syntax used here is not very common. The code looks like it is calling The Select () method of the employees set. However, the employees set is a common List <T> set and does not include this method. On the contrary, Select () is an extension method that is automatically provided to all IEnumerable <T> classes.

 

1. Extension method

The extension method allows you to define a method in a class, and then call it as if it was defined in other classes. The LINQ extension method is defined in the System. Linq. Enumerable class, but all IEnumerable <T> objects can be called.

Note:

       Because the LINQ extension method is defined in the System. Linq. Enumerable class, the class must be in the available range.

Check the definition of the Select () method:

Public static IEnumerable <TResult> Select <TSource, TResult> (
This IEnumerable <TSource> source, Func <TSource, TResult> selector)
{...}

The extension method must comply with the following rules:

  • All extension methods must be static.
  • The extension method can return any data type and receive any number of parameters.
  • The first parameter must be a reference to the object that calls the extension method (and followed by the keyword "this" before)
  • The data type of this parameter determines the available classes of the extension method.

The Select () method can be called by all examples of classes that implement IEnumerable <T> (determined by the this IEnumerable <TSource> source parameter ). Another parameter is used to obtain the delegate of the selected information segment. The returned value is an IEnumerable <T> object.

 

 

2. lambda expressions

       Lambda expressions in C # Are the new syntax of method-based LINQ expressions.The lambda expression is passed to the Select () method as follows:

Matches = employees. Select (employee => employee );

When Select () is called, the employees object is passed as the first parameter, which is the source of the query.The second parameter requires a delegate pointing to a method. This method executes the selection task and is called by each element in the set.

The Select () method receives a delegate. You can provide a common delegate (which points to the naming method defined elsewhere in the class), but doing so will make your code become lengthy.

A simpler solution is to use the anonymous method. The anonymous method starts with delegate, then the declaration of the method signature, and the code of the method is in parentheses. If you use the anonymous method, the previous example looks like this:

IEnumerable <EmployeeDetails> matches = employees
. Select (
Delegate (EmployeeDetails emp)
        {
Return emp;
        }
);

 

Lambda expressions are a way to make such code look more concise. A lambda expression is composed of two parts separated by "=>. The first part represents the parameters received by the anonymous method. For this example, the lambda expression receives each object in the set and exposes them through a reference Named employee. The second part of the lambda expression defines the value to be returned.

The following explicit LINQ expression extracts data from each employee and encapsulates the data into an anonymous response:

Var matches = employees
. Select (
Delegate (EmployeeDetails employee)
            {
Return new
                {
First = employee. FirstName,
Last = employee. LastName
};
            }
);

Now, you can use lambda expressions to simplify the code:

Var matches = employees. Select (employee =>
New {First = employee. FirstName, Last = employee. LastName });

 

3. Multipart expression

Of course, most of the LINQ expressions are more complex than the examples mentioned here. A more realistic LINQ expression may be added with sorting or filtering.

For example, the following code:

Matches = from employee in employees
Where employee. LastName. StartsWith ("D ")
Select employee;

You can use the displayed syntax to rewrite this expression:

Matches = employees
. Where (employee => employee. LastName. StartsWith ("D "))
. Select (employee => employee );

One advantage of explicit LINQ syntax is that it makes the operator order clearer. For the previous example, we can clearly see that it starts from the employees set, then calls Where (), and finally calls Select (). If you want to use more operators, you will face a longer set of method calls.

Where () provides a lambda expression to verify each element. If it should be included in the result, true is returned.

Select () provides a lambda expression to convert each data entry into the desired form.

 

       In most cases, the implicit syntax is used to create a LINQ expression. However, explicit syntax is used occasionally. For example, you need to pass a parameter that is not supported by the implicit LINQ syntax to the extension method.

       Understand how expressions map to call methods, how extension methods are bound to IEnumerable <T> objects, and how lambda expressions encapsulate, filter, sort, and project expressions. This makes the details of the internal work of LINQ clearer.

LINQ (implicit and lambda expressions)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.