• Linq基本子句


    由于个人在学校没有接触过Linq,而且在工作上运用Linq的时候也比较多,准备把LINQ的相关知识学习整理梳理一遍,希望能填补下这个知识点,也为未来减轻压力。

    LINQ查询表达式使用C#常见的语言构造,从外观上看,和我们常用的SQL类似,并且查询表达式中的变量可以用匿名类型,所以在很多情况下,不需要指定变量类型就可以构建LINQ表达式。

    LINQ的数据源可以是数据库对象或是XML流等,也可以使实现了IEnumerable或者泛型IEnumberable<T>接口的集合对象。

    LINQ的基本语法包含如下的8个上下文关键字,如下:

    关键字 说明
    from 指定范围变量和数据源
    where 根据bool表达式从数据源中筛选数据
    select 指定查询结果中的元素所具有的类型或表现形式
    group 对查询结果按照键值进行分组(IGrouping<TKey,TElement>)
    into 提供一个标识符,它可以充当对join、group或select子句结果的引用
    order 对查询出的元素进行排序(ascending/descending)
    join 按照两个指定匹配条件来Equals连接两个数据源
    let 产生一个用于存储查询表达式中的子表达式查询结果的范围变量

    1、From子句:

    如果要写一个LINQ表达式,就必须是以from子句开头。

                //单个form子句
                string[] values = { "学习使我快乐", "学习使我幸福", "爸爸叫我吃饭", "我充耳不闻" };
                var new_values = from value in values
                            where value.IndexOf("学习") > -1       //查询以"学习"开头的元素
                            select new { value, value.Length };
                foreach (var new_value in new_values)
                {
                    Console.WriteLine("{0},{1}", new_value.value, new_value.Length);
                }
                Console.ReadKey();
    
                //使用LINQ查询List集合
                List<Person> personList = new List<Person>();
                personList.Add(new Person { Name = "张三", Age = 20, Gender = '' });
                personList.Add(new Person { Name = "李四", Age = 21, Gender = '' });
                personList.Add(new Person { Name = "王五", Age = 22, Gender = '' });
    
                var new_personList = from Person person in personList
                            where person.Age > 20       //查询年龄大于20的人
                            select person;
                foreach (Person new_person in new_personList)
                {
                    Console.WriteLine("{0} 年龄:{1} 性别:{2}", new_person.Name, new_person.Age, new_person.Gender);
                }
                Console.ReadKey();
                //复合from子句
                List<Person> personList2 = new List<Person>()
                {
                    new Person{ Name = "张三", Age = 20, Phone = new List<string>(){"666666","138******"}},
                    new Person{ Name = "李四", Age = 21, Phone = new List<string>(){"777777","138******"}},
                    new Person{ Name = "王五", Age = 22, Phone = new List<string>(){"888888","138******"}}
                };
    
                //person、phone都是查询变量,作用域为当前查询语句
                var new_personList2 = from person in personList2
                                      from phone in person.Phone
                                      where phone.IndexOf("6666") > -1       //查询个人电话集合以"6666"开头的人
                                      select person;
                foreach (var new_person in new_personList2)
                {
                    Console.WriteLine("{0} 年龄{1}", new_person.Name, new_person.Age);
                    foreach (var person_phone in new_person.Phone)
                    {
                        Console.WriteLine("电话:{0}", person_phone);
                    }
                }
    
                Console.ReadKey();
    
                //4多个from子句
                var personList3 = from Person person in personList
                             where person.Age > 21       //查询集合1年龄超过21的人
                             from Person person2 in personList2
                             where person2.Age == 21       //查询集合2年龄等于21的人
                             select new { person, person2 };//查询结果定制
                foreach (var new_person in personList3)
                {
                    Console.WriteLine("{0}  {1}", new_person.person.Name, new_person.person2.Name);
                }
    
                Console.ReadKey();

    运行结果如下:

    2、Where子句:

    where子句是LINQ表达式的元素筛选机制,除了开始和结束的位置,它几乎可以出现在LINQ表达式的任意位置上。在一个LINQ表达式中,可以有where子句,也可以没有;可以有一个,也可以有多个;多个where子句之间的逻辑关系相当于逻辑“与”,每个where子句可以包含1个或多个bool逻辑表达式,这些条件成为谓词,谓词逻辑之间用的是“&&”或“||”等而不是SQL中的and 、or。

                //常见的where语句
                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张三三", Age = 20, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 21, Phone = "666666"},
                    new Person(){ Name = "王五", Age = 22, Phone = "777777"}
                };
    
                var new_personList = from person in personList
                                     where (person.Name.Length == 3 || person.Name.Substring(0, 1) == "") && person.Age > 20       //查询姓名长度为3或姓名以"李"开头且年龄大于20的人
                                     select new { person.Name, person.Age };
                foreach (var new_person in new_personList)
                {
                    Console.WriteLine("{0},{1}", new_person.Name, new_person.Age);
                }
    
                Console.ReadKey();
    
                //在where子句中使用自定义函数
                var new_personList2 = from Person person in personList
                             where person.Name.Length == 2
                             && Check(person.Name)       //查询姓名长度为2且符合自定义函数限定后的人
                             select person;
                foreach (var new_person in new_personList2)
                {
                    Console.WriteLine("{0},{1},{2}", new_person.Name, new_person.Age, new_person.Phone);
                }
                Console.ReadKey();
    
                //动态谓词的筛选
                //定义动态谓词数组,在实际开发中可以动态获得
                string[] names = { "李四", "XXX", "***", "@@@", "一些敏感词" };
    
                var new_personList3 = from Person person in personList
                             where !names.Contains(person.Name)       //查询姓名不包含集合元素的人
                             select person;
    
                foreach (var new_person in new_personList3)
                {
                    Console.WriteLine("{0} 年龄:{1},电话:{2}", new_person.Name, new_person.Age, new_person.Phone);
                }
                Console.ReadKey();
            //自定义函数
            static bool Check(string name)
            {
                if (name.Substring(0, 1) == "")
                    return false;
                return true;
            }

    运行结果如下:

     3、Select子句:

    在select子句上可以非常灵活的处理查询到的元素,然后再把结果返回。

                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张三", Age = 20, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 21, Phone = "666666"},
                    new Person(){ Name = "王五", Age = 22, Phone = "777777"}
                };
    
                //常见的select语句
                var new_personList = from person in personList
                                     where person.Age >= 22 && person.Age <= 30       //查询年龄大于等于22小于等于30的人
                                     select new { person.Name, person.Age };       //处理查询结果,返回查到的人的姓名和年龄
    
                foreach (var new_person in new_personList)
                {
                    Console.WriteLine(new_person.Name + “ 年龄:” + new_person.Age);
                }
                Console.ReadKey();
    
                //对查询到的结果集进行替换
                var new_personList2 = from person in personList
                                      where person.Age >= 21 && person.Age <= 30       //查询年龄大于等于22小于等于30的人
                                      select person.Name.Replace("", "");       //处理查询结果,返回查到的人的姓名替换后的结果
    
                foreach (var new_person in new_personList2)
                {
                    Console.WriteLine(new_person);
                }
                Console.ReadKey();
    
                //在select子句中使用自定义函数
                var new_personList3 = from person in personList
                                      where person.Age >= 20 && person.Age <= 21       //查询年龄大于等于20小于等于21的人
                                      select MyDesc(person.Name);       //处理查询结果,返回自定义函数处理后的人的姓名
    
                foreach (var new_person in new_personList3)
                {
                    Console.WriteLine(new_person);
                }
                Console.ReadKey();
    
                //对查询结果进行投影
                var new_personList4 = from person in personList
                                      where person.Age >= 21 && person.Age <= 22       //查询年龄大于等于21小于等于22的人
                                      select new NewPerson { Name = "我的名字叫:" + person.Name, Age = person.Age + 1 };       //处理查询结果,返回投影结果
    
                foreach (var new_person in new_personList4)
                {
                    Console.WriteLine(new_person.Name + new_person.Age);
                }
                Console.ReadKey();
            static string MyDesc(string s)
            {
                return s + "好帅";
            }
        public class NewPerson
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }

    运行结果如下:

     4、Group子句:

    LINQ表达式必须以from子句开头,以select或group子句结束,所以除了使用select来返回结果外,也可以使用group子句来返回元素分组后的结果。group子句返回的是一个基于IGrouping<TKey,TElement>泛型接口的对象序列。

    注意:语法和SQL的group有点区别。

                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张一", Age = 20, Phone = "333333"},
                    new Person(){ Name = "张二", Age = 21, Phone = "444444"},
                    new Person(){ Name = "张三", Age = 22, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 23, Phone = "666666"},
                    new Person(){ Name = "李五", Age = 24, Phone = "777777"},
                    new Person(){ Name = "赵六", Age = 25, Phone = "888888"},
                    new Person(){ Name = "田七", Age = 26, Phone = "999999"},
                };
    
                var new_personList = from person in personList
                                     group person by person.Name.Substring(0, 1);       //按姓氏进行分组
    
                //遍历键值和键值所属元素
                foreach (IGrouping<string, Person> new_person in new_personList)
                {
                    Console.WriteLine();
                    Console.WriteLine("姓:{0} ", new_person.Key);
                    foreach (var p in new_person)
                    {
                        Console.WriteLine("{0} 年龄:{1}  电话:{2}", p.Name, p.Age, p.Phone);
                    }
                }
                Console.ReadKey();
    
                Console.WriteLine();
                Console.WriteLine("-----------------------------------");
    
                var new_personList2 = from person in personList
                                      group person by person.Age > 23;       //按年龄是否大于23进行分组
    
                foreach (IGrouping<bool, Person> new_person in new_personList2)
                {
                    Console.WriteLine();
                    Console.WriteLine("年龄 {0} 23 ", new_person.Key ? "大于" : "小于");
                    foreach (var p in new_person)
                    {
                        Console.WriteLine("{0} 年龄:{1}  电话:{2}", p.Name, p.Age, p.Phone);
                    }
                }
                Console.ReadKey();

    运行结果如下:

     5、Into子句:

    into子句作为一个临时标识符,用于group、select、join子句中充当其结果的引用。

                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张一", Age = 20, Phone = "333333"},
                    new Person(){ Name = "张二", Age = 21, Phone = "444444"},
                    new Person(){ Name = "张三", Age = 12, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 23, Phone = "666666"},
                    new Person(){ Name = "李五", Age = 14, Phone = "777777"},
                    new Person(){ Name = "赵六", Age = 25, Phone = "888888"},
                    new Person(){ Name = "田七", Age = 16, Phone = "999999"},
                };
    
                //into用于group子句
                var new_personList = from person in personList
                                     group person by person.Name.Substring(0, 1) into person_group       //相当于分组后的组名
                                     select person_group;
    
                foreach (var persontGroup in new_personList)
                {
                    Console.WriteLine("姓:{0} ", persontGroup.Key);
                    foreach (var p in persontGroup)
                    {
                        Console.WriteLine("{0} 电话:{1}", p.Name, p.Phone);
                    }
                }
                Console.ReadKey();
                Console.WriteLine();
    
                //select子句中的into子句
                var new_personList2 = from person in personList
                                      select new { NewName = person.Name, NewAge = person.Age } into newperson       //相当于创建一个新的对象
                                      orderby newperson.NewAge
                                      select newperson;
                
                foreach (var persontGroup in new_personList2)
                {
                    Console.WriteLine("{0} 年龄:{1}", persontGroup.NewName, persontGroup.NewAge);
                }
    
                Console.ReadKey();

    运行结果如下:

    6、OrderBy子句:

    按照元素的一个或多个属性对元素进行排序。

                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张一", Age = 20, Phone = "333333"},
                    new Person(){ Name = "张二二", Age = 20, Phone = "444444"},
                    new Person(){ Name = "张三", Age = 12, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 23, Phone = "666666"},
                    new Person(){ Name = "李五", Age = 14, Phone = "777777"},
                    new Person(){ Name = "赵六", Age = 25, Phone = "888888"},
                    new Person(){ Name = "田七", Age = 16, Phone = "999999"},
                };
    
                //按照年龄排序
                var new_personList = from person in personList
                                     orderby person.Age       //默认升序ascending,如果要降序要加上descending
                                     select person;
    
                foreach (var new_person in new_personList)
                {
                    Console.WriteLine("{0} 年龄:{1} 电话:{2}", new_person.Name, new_person.Age, new_person.Phone);
                }
                Console.ReadKey();
                Console.WriteLine();
    
                //按照年龄进行降序排序,按照名字字数进行次要排序
                var new_personList2 = from person in personList
                                      orderby person.Age descending, person.Name.Length descending
                                      select person;
    
                foreach (var new_person in new_personList2)
                {
                    Console.WriteLine("{0} 年龄:{1} 电话:{2}", new_person.Name, new_person.Age, new_person.Phone);
                }
                Console.ReadKey();

    运行结果如下:

     7、Let子句:

    let子句用于在LINQ表达式中存储子表达式的计算结果。

                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张一", Age = 20, Phone = "333333"},
                    new Person(){ Name = "张二二", Age = 20, Phone = "444444"},
                    new Person(){ Name = "张三", Age = 12, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 23, Phone = "666666"},
                    new Person(){ Name = "李五", Age = 14, Phone = "777777"},
                    new Person(){ Name = "赵六", Age = 25, Phone = "888888"},
                    new Person(){ Name = "田七", Age = 16, Phone = "999999"},
                };
    
                //使用let子句创建范围变量g,并通过g构建查询表达式
                var new_personList = from person in personList
                                     let g = person.Name.Substring(0, 1)
                                     where g == "" || g == ""
                                     select person;
    
                foreach (var new_person in new_personList)
                {
                    Console.WriteLine("{0} 年龄:{1} 电话:{2}", new_person.Name, new_person.Age, new_person.Phone);
                }
                Console.ReadKey();
                Console.WriteLine();
    
                //也可以不使用let,上面的语句等效于下
                var new_personList2 = from person in personList
                                      where person.Name.Substring(0, 1) == "" || person.Name.Substring(0, 1) == ""
                                      select person;
    
                foreach (var new_person in new_personList2)
                {
                    Console.WriteLine("{0} 年龄:{1} 电话:{2}", new_person.Name, new_person.Age, new_person.Phone);
                }
                Console.ReadKey();

    运行结果如下:

    8、Join子句:

    join子句能将两个数据源中元素可以进行相等比较的两个属性进行关联。使用equals关键字进行相等比较,而不是常用的双等号。

                //定义两个数据源
                List<Person> personList = new List<Person>()
                {
                    new Person(){ Name = "张三", Age = 12, Phone = "555555"},
                    new Person(){ Name = "李四", Age = 23, Phone = "666666"},
                    new Person(){ Name = "王五", Age = 14, Phone = "777777"},
                    new Person(){ Name = "赵六", Age = 25, Phone = "888888"},
                    new Person(){ Name = "田七", Age = 16, Phone = "999999"},
                };
    
                List<PersonFile> personFileList = new List<PersonFile>()
                {
                    new PersonFile(){ Name = "张三", File = "三好学生"},
                    new PersonFile(){ Name = "李四", File = "班长"},
                    new PersonFile(){ Name = "王五", File = "学习委员"},
                    new PersonFile(){ Name = "赵六", File = "差生"}
                };
    
                //根据姓名进行内连接
                var new_personList = from person in personList
                                     join file in personFileList on person.Name equals file.Name
                                     select new { Name = person.Name, file = file.File, Age = person.Age };
    
                foreach (var new_person in new_personList)
                {
                    Console.WriteLine("{0} {1} 年龄:{2}", new_person.Name, new_person.file, new_person.Age);
                }
                Console.ReadKey();
                Console.WriteLine();
    
                //等效于前面的多个from的效果
                var new_personList2 = from person in personList
                                      from file in personFileList
                                      where person.Name == file.Name
                                      select new { Name = person.Name, File = file.File, Age = person.Age };
    
                foreach (var new_person in new_personList2)
                {
                    Console.WriteLine("{0} {1} 年龄:{2}", new_person.Name, new_person.File, new_person.Age);
                }
                Console.ReadKey();
                Console.WriteLine();
    
                //根据姓名进行分组连接
                var new_personList3 = from person in personList
                                      join file in personFileList on person.Name equals file.Name into person_group
                                      select new { Name = person.Name, Files = person_group };
    
                foreach (var new_person in new_personList3)
                {
                    Console.WriteLine(new_person.Name);
                    foreach (var p in new_person.Files)
                    {
                        Console.WriteLine(p.File);
                    }
                }
                Console.ReadKey();
                Console.WriteLine();
    
                //根据姓名进行左外连接
                var new_personList4 = from person in personList
                                      join file in personFileList on person.Name equals file.Name into person_group
                                      from position in person_group.DefaultIfEmpty()
                                      select new { Name = person.Name, File = position == null ? "" : position.File };
                foreach (var new_person in new_personList4)
                {
                    Console.WriteLine("{0}  {1}  ", new_person.Name, new_person.File);
                }
                Console.ReadKey();

    运行结果如下:

     

     对Linq的基本子句用法学习和总结完毕,还有待继续练习达到灵活运行!

  • 相关阅读:
    第二次冲刺 站立会议7
    第二次冲刺 站立会议6
    第二次冲刺 站立会议5
    第二次冲刺 站立会议4
    第二次冲刺 站立会议3
    第二次冲刺 站立会议2
    第二次冲刺 站立会议1
    第一次冲刺 站立会议9
    第一次冲刺 站立会议8
    第一次冲刺 站立会议7
  • 原文地址:https://www.cnblogs.com/jiechou/p/9175794.html
Copyright © 2020-2023  润新知