# LINQ

Language INtegrated Query(LINQ),这是C#语言的一个扩展,将数据查询直接集成到C#中,在没有LINQ时,完成这类任务需要额外的代码,LINQ提供了一种可移植的方式,来查询,排序和分组许多不同的种类的数据(XML,JSON,SQL数据库,对象集合,Web服务,企业目录)。

# LINQ_To_XML

LINQ to XML 是用于XML的一组附加类,它更方便XML的操作,这个类在using System.Xml.Linq命名空间中。LINQ to XML提供了一种构建XML更快捷的方式,称为函数构造方式(functional construction),在这种方式中,构造函数的调用可以用反映XML文档结构的方式嵌套,如下面示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using static System.Console;
using System.Collections;
using System.Xml.Linq;

namespace LearnCSharp1
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument xdoc = new XDocument(
                new XElement("persons",
                    new XElement("person",
                        new XElement("name","li"),
                        new XElement("age",20),
                        new XElement("score",100)
                    ),
                    new XElement("person",
                        new XAttribute("test","stu2"),
                        new XElement("name", "wang"),
                        new XElement("age", 18),
                        new XElement("score", 90)
                    ),
                    new XElement("person",
                        new XAttribute("identity","stu"),
                        new XElement("name", "zhang"),
                        new XElement("age", 24),
                        new XElement("score", 80)
                    )
                )
            );
            xdoc.Save("persons.xml");
            XElement xReader = XElement.Load("persons.xml");
            Console.WriteLine("Content is:");
            Console.WriteLine(xReader);
            Console.ReadLine();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# LINQ相关

.Net Framework 4.7中有许多内置的LINQ提供的程序,LINQ to XML只是它提供的一种,除此之外它还有:

  • LINQ to Objects:对任何类型的C#内存中对象提供查询,比如数组,列表和其他集合类型。
  • LINQ to XML:使用与其他LINQ变体相同的语法和通用查询机制,来创建和操纵XML文档。
  • LINQ to Entities:Entity Framework是 .Net中最新的数据接口类,被官方建议使用。
  • LINQ to Data Set:DataSet在 .Net Framework第一版引入,这个变体支持使用LINQ方便地查询旧的 .Net数据。
  • LINQ to SQL:它取代了LINQ to Entities。
  • PLINQ:是并行LINQ,用并行数据库扩展了LINQ to Objects,可以拆分查询,在多核处理器上同时执行。
  • LINQ to JSON:包含在Newtonsoft包中,这个库支持使用与其他LINQ变体相同的语法和通用查询机制,来创建和操纵JSON文档。

# LINQ查询语法

看下面示例用法:

static void Main(string[] args)
{
    string[] entitySets = { "Apple", "Banana","Orange","Brick","Book","block","chair","light"};
    var queryResult = from entity in entitySets 
                      where entity.StartsWith("B") 
                      select entity;
    Console.WriteLine("Entity starts with B:");
    foreach(var item in queryResult)
    {
        Console.WriteLine(item);
    }
    Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13

要使用LINQ查询,目标得实现IEnumerable<T>接口的类型。就像是SQL语句的C#语言化:

语句 | LINQ | SQL --- | --- from | 指定数据源 | 指定数据表 where | 指定条件 | 指定条件 select | 选择元素 | 选择元素

# LINQ方法语句

使用LINQ完成任务时也有多种方式,上面使用的是查询语法,这是在LINQ中编写查询的首选方式,因为它一般更容易被理解,下个示例使用LINQ的方法语法,也称为方法语法,大多数方法语法都要求传送一个方法或函数,方法/函数参数以委托形式传送,一般会传送一个Lambda的匿名函数。

static void Main(string[] args)
{
    string[] entitySets = { "Apple", "Banana","Orange","Brick","Book","block","chair","light"};
    var queryResult = entitySets.Where(one => one.StartsWith("B"));
    Console.WriteLine("Entity starts with B:");
    foreach(var item in queryResult)
    {
        Console.WriteLine(item);
    }
    Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11

# 排序查询结果

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using static System.Console;
using System.Collections;
using System.Xml.Linq;

namespace LearnCSharp1
{
    class Program
    {
        static void PrintContent(IEnumerable target)
        {
            foreach(var one in target)
            {
                Console.WriteLine(one);
            }

        }
        static void Main(string[] args)
        {
            string[] entitySets = { "Apple", "Banana","Orange","Brick","Book","block","chair","light"};
            var queryResult = entitySets.Where(one => one.StartsWith("B")).OrderBy(n => n);
            var queryResult2 = from entity in entitySets
                               where entity.StartsWith("B")
                               orderby entity descending
                               select entity;
            var queryResult3 = from entity in entitySets
                               where entity.StartsWith("B")
                               orderby entity.Substring(entity.Length-1)
                               select entity;
            Console.WriteLine("--------------Entity starts with B order by normal:");
            PrintContent(queryResult);
            Console.WriteLine("--------------order by descending");
            PrintContent(queryResult2);
            Console.WriteLine("--------------order by last subtitle");
            PrintContent(queryResult3);
            Console.ReadKey();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 聚合运算符

聚合运算符可帮助分析查询的结果,比如得到查询结果的个数,最大值最小值等。下面的Distinct方法在显示数据时去掉重复值了。

class Program
{
    static void PrintContent(IEnumerable target)
    {
        foreach(var one in target)
        {
            Console.WriteLine(one);
        }

    }
    static void Main(string[] args)
    {
        int[] numSets = { 1,5,3,2,9,9,10,13,23,12};
        var queryResult = from num in numSets 
                           where num>8
                           select num;

        Console.WriteLine("------------Only Display Distinct Result:--------------------------");
        PrintContent(queryResult.Distinct());
        Console.WriteLine("------------GetResultCountNumber:------------");
        Console.WriteLine(queryResult.Count());
        Console.WriteLine("------------Max Number:-----------------------");
        Console.WriteLine(queryResult.Max());
        Console.WriteLine("------------Min Number:-----------------------");
        Console.WriteLine(queryResult.Min());
        Console.WriteLine("------------Average Number:-----------------------");
        Console.WriteLine(queryResult.Average());
        Console.WriteLine("------------Sum Number:-----------------------");
        Console.WriteLine(queryResult.Sum());
       }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 其他查询

还涉及到多级排序(按多个字段排序),分组查询,join连接查询。看下面示例:

class Program
{
    class student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public int Score { get; set; }
        public string Area { get; set; }

        public override string ToString()
        {
            return $"Name:{Name},Age:{Age},Score:{Score},Area:{Area}";
        }
    }

    class stuInfo
    {
        public string Name { set; get; }
        public int Money { set; get; }
    }
    static void PrintContent(IEnumerable target)
    {
        foreach (var one in target)
        {
            Console.WriteLine(one);
        }

    }
    static void Main(string[] args)
    {
        List<student> students = new List<student>
        {
            new student
            {
                Name="zhang",
                Age = 12,
                Score=68,
                Area="tianjin",
            },
            new student
            {
                Name="li",
                Age=18,
                Score=78,
                Area="tianjin",
            },
            new student
            {
                Name="liu",
                Age=20,
                Score=89,
                Area="hebei",
            },
            new student
            {
                Name="yuan",
                Age=30,
                Score=89
            },
            new student
            {
                Name="huo",
                Age=40,
                Score=100
            },
        };
        List<stuInfo> studentsInfo = new List<stuInfo>() { 
            new stuInfo
            {
                Name="zhang",
                Money=1000,
            },
            new stuInfo
            {
                Name="li",
                Money=4000,
            },
            new stuInfo
            {
                Name="liu",
                Money=2000,
            },
            new stuInfo
            {
                Name="yuan",
                Money=3000,
            },
            new stuInfo
            {
                Name="huo",
                Money=6000,
            },
        }; 
        //多级排序,按多个字段排序
        var queryResult = from stu in students
                           orderby stu.Score,stu.Age
                           select stu;
        PrintContent(queryResult);
        //分组查询
        var queryResult2 = from stu in students
                           group stu by stu.Area into stuGroup
                           select new { AreaScore = stuGroup.Sum(stu => stu.Score) ,Area=stuGroup.Key};
        PrintContent(queryResult2);
        //join查询
        var queryResult3 = from stu in students
                           join stuI in studentsInfo on stu.Name equals stuI.Name
                           select new { stu.Name, stu.Age, stu.Score, stu.Area, stuI.Money };
        PrintContent(queryResult3);

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111