(11) CSharp-LINQ-Query Expression (2)

1. Query expression

1. The structure of the query expression

A query expression consists of a from clause and a query body.

  • Clauses must appear in a certain order.
  • Both the from clause and the select...group clause are required.
  • Other clauses are optional.
  • In a LINQ query expression, the select clause comes last in the expression.
  • There can be as many from...let...where clauses as desired.

Please add a picture description

2. from clause

The from clause specifies the data collection to use as the data source. It also introduces iteration variables.

Main points:

  • 1) The iteration variable represents each element of the data source one by one.

  • 2) The syntax of the from clause is as follows:

    • Type is the type of elements in the collection. This is optional since the compiler can infer the type from the collection.
    • Item is the name of the iteration variable.
    • Items is the name of the collection to query. Collections must be enumerable.
from Type Item in Items
//迭代变量声明:Type Item in Items
int arr1 = {10,11,12,13};

var query = from item in arr1
		    where item < 13
		    select item;

foreach(var item in query)
Console.Write($"{ item },");
//迭代变量:item

Output result:

10,11,12,

Diagram demonstrating the syntax of the from clause

Please add a picture description

LINQ's from clause is very similar to the foreach statement, but the main differences are as follows:

  • The foreach statement imperatively specifies that the items in the collection are to be accessed sequentially, from first to last. The from clause, on the other hand, declaratively specifies that each item in the collection is to be visited, but does not assume in what order.

  • A foreach statement executes its body when it encounters code, while a from clause executes nothing. It creates code-behind objects that can execute queries. A query is executed only when the program's control flow encounters a statement that accesses a query variable.

3, join child clause

Key points about associations:

  • Use joins to combine data from two or more collections.
  • The join operation takes two collections and creates a temporary collection of objects, each of which contains all the fields from the two original collection objects.

The join syntax is as follows, which specifies that the second set is to be joined with the set in the preceding clause:

join Identifier in Collection2 on Field1 equals Field2
//关键字:join、in、on、equals
//指定另外的集合和 ID 来引用它:Identifier in Collection2
//用于比较相等性的字段:Field1 equals Field2

Figure 20-4 demonstrates the syntax of the join clause:

Please add a picture description

Examples of join clauses

var query = from s in students
			join c in studentsInCourses on s.StID equals c.StID

//第一个集合和 ID:from s in students
//第二集合和 ID:c in studentsInCourses
//第一个集合的项:s.StID
//第二集合的项:c.StID

what is connection

A join in LINQ takes two collections and creates a new collection where each element contains elements from both original collections.

public class Student
{
public int StID;
public string LastName;
}

public class CourseStudent
{
public string CourseName;
public inr StID;
}

As shown in the figure:
The Student object is students, and the CourseStudent object is studentsInCourses.

Please add a picture description

* Figure 20-6 demonstrates how joins work.

If we take the first student's record and compare its ID to the student ID in each of the studentsInCourses objects, we find two matching records, the top of the middle column.

Please add a picture description

Example:


    class Program
    {
        public class Student
        {
            public int StID;
            public string LastName;
        }

        public class CourseStudent
        {
            public string CourseName;
            public int StID;
        }

        static Student[] students = new Student[]
        {
            new Student { StID = 1, LastName = "Carson" },
            new Student { StID = 2, LastName = "Klassen" },
            new Student { StID = 3, LastName = "Fleming" },

        };

        static CourseStudent[] studentsInCourses = new CourseStudent[]
        {
            new CourseStudent { CourseName = "Art",     StID = 1 },
            new CourseStudent { CourseName = "Art",     StID = 2 },
            new CourseStudent { CourseName = "History",     StID = 1 },
            new CourseStudent { CourseName = "History",     StID = 3 },
            new CourseStudent { CourseName = "Physics",     StID = 3 },
        };

        static void Main(string[] args)
        {
            var query = from s in students
                        join c in studentsInCourses on s.StID equals c.StID
                        where c.CourseName == "History"
                        select s.LastName;

            foreach (var q in query)
                Console.WriteLine($"Student taking History: { q }");
                             
            Console.ReadKey();
        }
    }

Output result:

Student taking History: Carson
Student taking History: Fleming

4. The from...let...where fragment in the query body

The optional from...let...where part is the first part of the query body and can consist of any number of 3 subclauses - from clause, let clause and where clause.

1) from clause

A query expression begins with the required from clause, followed by the query body. The body itself can begin with any number of other from clauses, each of which specifies an additional set of source data and introduces iteration variables to be evaluated later.

Please add a picture description

Example:

      static void Main(string[] args)
        {
            var groupA = new[] { 3, 4, 5, 6 };
            var groupB = new[] { 6, 7, 8, 9 };

            var someInts = from a in groupA//必需的第一个 from 子句
                           from b in groupB//查询主体的第一个子句
                           where a > 4 && b <= 8
                           select new { a, b, sum = a + b };//匿名类型对象

            foreach (var x in someInts)
                Console.WriteLine(x);

            Console.ReadKey();
        }

Output result:

{ a = 5, b = 6, sum = 11 }
{ a = 5, b = 7, sum = 12 }
{ a = 5, b = 8, sum = 13 }
{ a = 6, b = 6, sum = 12 }
{ a = 6, b = 7, sum = 13 }
{ a = 6, b = 8, sum = 14 }

2) let clause

The let clause takes an expression operation and assigns it to an identifier to be used in other operations.

The syntax of the let clause is as follows:

let Identifier = Expression

Example:

static void Main(string[] args)
        {
            var groupA = new[] { 3, 4, 5, 6 };
            var groupB = new[] { 6, 7, 8, 9 };

            var someInts = from a in groupA
                           from b in groupB
                           let sum = a + b //在新的变量中保存结果
                           where sum == 12
                           select new { a, b, sum};

            foreach (var x in someInts)
                Console.WriteLine(x);

            Console.ReadKey();
        }

Output result:

{ a = 3, b = 9, sum = 12 }
{ a = 4, b = 8, sum = 12 }
{ a = 5, b = 7, sum = 12 }
{ a = 6, b = 6, sum = 12 }

3) where child clause

The ==where clause removes items that do not meet the specified conditions according to subsequent operations. The ==where clause is as follows:

where BooleanExpression

Important points about where:

  • A query expression can have any number of where clauses as long as it is in the from...let...where part.
  • An item must satisfy all where clauses to avoid being removed later.
    static void Main(string[] args)
        {
            var groupA = new[] { 3, 4, 5, 6 };
            var groupB = new[] { 6, 7, 8, 9 };

            var someInts = from a in groupA
                           from b in groupB
                           let sum = a + b 
                           where sum >= 11//条件1
                           where a == 4 //条件2
                           select new { a, b, sum };

            foreach (var x in someInts)
                Console.WriteLine(x);

            Console.ReadKey();
        }

Output result:

{ a = 4, b = 7, sum = 11 }
{ a = 4, b = 8, sum = 12 }
{ a = 4, b = 9, sum = 13 }

Two, orderby clause

The orderby clause takes an expression andreturn result items in order

optionalThe ascending and descending keywords set the sort direction. An expression is usually a field of an item. The field does not have to be a numeric field, it can also be a sortable type like a string.

  • The default ordering for the orderby clause is ascending. We can then explicitly set the ordering of elements using the ascending and descending keywords toascending or descending
  • There can be any number of clauses and they must be separated by commas.
       static void Main(string[] args)
        {
            var students = new[]
            {
              new { LName = "Jones", FName = "Mary" , Age = 19, Major = "History" },
              new { LName = "Smith", FName = "Bob" , Age = 20, Major = "CompSci" },
              new { LName = "Fleming", FName = "Carol" , Age = 21, Major = "History" },
          };

            var query = from student in students
                        orderby student.Age//根据年龄排序
                        select student;

            foreach (var s in query)
                Console.WriteLine($"{ s.LName },{ s.FName },{ s.Age },{ s.Major }");

            Console.ReadKey();
        }

Output result:

Jones,Mary,19,History
Smith,Bob,20,CompSci
Fleming,Carol,21,History

3. select...group clause

The select...group section consists of two types of clauses - select clauses and group...by clauses. The clauses preceding the select...group part specify the data source and objects to select.

The function of the select...group part is as follows:

  • 1) The ==select clause specifies which parts of the selected object should be selected by the application. == It can specify any of the following.

    • the entire data item.
    • A field of a data item.
    • A new object consisting of several fields in the data item. (or similar other value)
  • 2)The group...by clause is optional and specifies how the selected items are grouped.

Example:

       static void Main(string[] args)
        {
            var students = new[]
            {
              new { LName = "Jones", FName = "Mary" , Age = 19, Major = "History" },
              new { LName = "Smith", FName = "Bob" , Age = 20, Major = "CompSci" },
              new { LName = "Fleming", FName = "Carol" , Age = 21, Major = "History" },
          };

            var query = from s in students
                        select s;

            foreach (var q in query)
                Console.WriteLine($"{ q.LName },{ q.FName },{ q.Age },{ q.Major }");

            Console.ReadKey();
        }

Output result:

Jones,Mary,19,History
Smith,Bob,20,CompSci
Fleming,Carol,21,History

You can also use the select clause to select certain fields of an object.

var query = from s in students
			select s.LName;

foreach(var q in query)
Console.WriteLine(q);

Output result:

Jones
Smith
Fleming

4. Anonymous types in queries

Query results can consist of items from the original collection, fields from items in the original collection, or anonymous types.

select new { s.LastNmae, s.FirstName, s.Major };

Example:

       static void Main(string[] args)
        {
            var students = new[]
            {
              new { LName = "Jones", FName = "Mary" , Age = 19, Major = "History" },
              new { LName = "Smith", FName = "Bob" , Age = 20, Major = "CompSci" },
              new { LName = "Fleming", FName = "Carol" , Age = 21, Major = "History" },
          };

            var query = from s in students
                        select new { s.LName, s.FName, s.Major };

            foreach (var q in query)
                Console.WriteLine($"{ q.LName },{ q.FName } -- { q.Major }");

            Console.ReadKey();
        }

//创建匿名类型:s.LName, s.FName, s.Major
//匿名类型的访问字段:q.LName、q.FName、q.Major

Output result:

Jones,Mary – History
Smith,Bob – CompSci
Fleming,Carol – History

Five, group clause

The group clause groups the selected objects according to the specified criteria.

Important points about the group clause:

  • If items are included in the query's results, they can be grouped based on the value of a field. The attribute by which the grouping is based is called the key.

  • The group clause returns not an enumeration of items in the original data source, but an enumerable type that can enumerate groupings of already formed items.

  • Groups themselves are enumerable types, and they enumerate the actual items.

group student by student.Majot;

Example:

      static void Main(string[] args)
        {
            var students = new[]
            {
              new { LName = "Jones", FName = "Mary" , Age = 19, Major = "History" },
              new { LName = "Smith", FName = "Bob" , Age = 20, Major = "CompSci" },
              new { LName = "Fleming", FName = "Carol" , Age = 21, Major = "History" },
          };

            var query = from student in students
                        group student by student.Major;

            foreach (var g in query)//枚举分组
            {
                Console.WriteLine("{0}", g.Key);

                foreach (var s in g)//枚举分组中的项
                    Console.WriteLine($"   { s.LName },{ s.FName }");
            }

            Console.ReadKey();
        }

//分组键:g.Key

Output result:

History
Jones,Mary
Fleming,Carol
CompSci
Smith,Bob

Figure 20-10 illustrates the objects returned from a query expression and stored in query variables.

  • The object returned from a query expression is an enumerable type that enumerates the grouped results from the query.
  • Each group is distinguished by a field called a key.
  • Each group is itself an enumerable type and its items can be enumerated.

Please add a picture description

6. Query continuation: into clause

A query continuation clause can take the result of one part of a query and give it a name so it can be used in another part of the query.

Example:

        static void Main(string[] args)
        {
            var groupA = new[] { 3, 4, 5, 6 };
            var groupB = new[] { 4, 5, 6, 7 };

            var someInts = from a in groupA
                           join b in groupB on a equals b
                           into groupAandB //查询延续
                           from c in groupAandB
                           select c;

            foreach (var v in someInts)
                Console.Write($"{ v } ");

            Console.ReadKey();
        }

Output result:

4 5 6

Guess you like

Origin blog.csdn.net/chen1083376511/article/details/131344062