linq总结系列(一)---基础部分

一、linq的基本概念

  LINQ是C#和VB中的统一查询语法,使用对象来保存和检索来自不同来源(如数据库、xml、对象集合)的数据。

  主要功能:消除了编程语言和数据库之间的不匹配,以及为不同类型的数据源提供统一的查询接口。

  适用范围:LInq适用于实现了IEnumerable <T>(IQueryable继承于IEnumerable )的实例,如:List,Dictionary,Queue,LinkedList,Array等

二、linq的使用

  有两种方法可以将LINQ查询写入IEnumerable集合或IQueryable数据源。

  1、查询语法

    特点:以from子句开头,可以以select或groupBy子句结束

  2、lambda表达式(简洁且功能更多,推荐)

  下边给出了简单的例子,注:后边的部分都是使用的这个测试数据。

 1   //准备的测试数据
 2             IList<UserInfo> userList = new List<UserInfo>() { 
 3                  new UserInfo() { UId = 1, UserName = "zs", Age = 23 ,RoleId=1} ,
 4                  new UserInfo() { UId = 2, UserName = "ls", Age = 20 ,RoleId=2},
 5                  new UserInfo() { UId = 3, UserName = "ww", Age = 33 ,RoleId=1},
 6                  new UserInfo() { UId = 4, UserName = "zl", Age = 26 ,RoleId=2},
 7                  new UserInfo() { UId = 5, UserName = "tq", Age = 42 ,RoleId=2} 
 8               };//用户列表
 9             IList<RoleInfo> roleList = new List<RoleInfo>(){
10                 new RoleInfo(){Rid=1,RoleName="管理员"},
11                 new RoleInfo(){Rid=2,RoleName="普通用户"},
12             };//角色列表
13 
14             //query语法
15             var resUsers = from u in userList
16                            where u.Age > 20
17                            select new {u.UId,u.UserName,u.Age};
18             //lambda
19             var resUsers2 = userList.Where<UserInfo>(u => u.Age > 20).Select
                  (u => new { u.UId,u.UserName,u.Age});

 

三、linq详解

1、过滤 (where 和 oftype)

  Where:根据给定的条件表达式过滤集合,并返回一个新集合

  OfType:根据类型进行过滤

1        IList<object> list = new List<object>() { 1, "hello", user };//user是一个UserInfo的实例
2             //query语法
3               var result = from o in list.OfType<string>()
4                            select o;
5             //lambda语法
6               var result2 = list.OfType<string>();

2、排序(OrderBy,OrderByDescending,ThenBy,ThenByDescending)

1     //对userList先按Id排序,再按Age排序
2             //query语法
3             var result = from u in userList
4                          orderby u.Id,u.Age descending
5                          select u;
6             //lambda语法  
7             var result2 = userList.OrderByDescending(u => u.Id).ThenBy(u=>u.Age);

3、分组(group by,ToLookUp)

       //query语法
              var resGroups = from u in userList
                              group u by u.RoleId;
         //lambda方式  注:GroupBy延迟执行,而ToLookup是立即执行的,使用方法和GroupBy一样。
              var resGroups2 = userList.GroupBy(u => u.RoleId);
              //遍历(group.Key为设置分组的列的值)
             foreach (var group in resGroups)
              {
                  Console.WriteLine("roleId:{0}", group.Key);
                 foreach (UserInfo user in group)
                 {
                    Console.WriteLine("UserName:{0}", user.UserName);
                 }
             }
             /*结果:  roleId:1
                     UserName:zs
                     UserName:ww
                     roleId:2
                     UserName:ls
           UserName:zl 21  UserName:tq */
    
//多列分组
    var productGroup=
        from p in db.Products
        group p by new
        {
            p.PName,
            p.PColor
        }
        into g
        select new
                {
                    g.Key,//这里的key是一个对象,有两个属性:PName,PColor
                    g
                };
 

 

4、连接查询(join)

   //query语法,查询用户名和该用户所属的角色 inner join
             var resJoin = from user in userList
                           join role in roleList
                          on user.RoleId equals role.Rid
                          select new
                           {
                               uname=user.UserName,
                              rname=role.RoleName
                           };
 
    //left join,right join调整下顺序即可
    var resJoin = from user in userList
                          join role in roleList
                          on user.RoleId equals role.Rid into temp
                from tt in temp.DefaultIfEmpty
                           select new
                          {
                              uname=user.UserName,
                              rname=role?.RoleName
                           };
    //cross join
    var resJoin = from user in userList
                        from role in roleList
                               select new
                              {
                                  uname=user?.UserName,
                                  rname=role?.RoleName
                              };

         //lambda方式
             var resJoin2 = userList.Join(roleList, 
                 user => user.RoleId,  //outkey
                 role => role.Rid,     //innerkey
                 (user, role) => new   //result
                 {
                     uname = user.UserName,
                     rname = role.RoleName
                 });
             //遍历
             foreach (var item in resJoin2)
             {
                 Console.WriteLine("用户:{0}----角色:{1}", item.uname, item.rname);
             }
 
             /*结果:  用户:zs----角色:管理员
                     用户:ls----角色:普通用户
                     用户:ww----角色:管理员
                     用户:zl----角色:普通用户
                     用户:tq----角色:普通用户 */

5、linq中的量词(All,Any,Contains)

 1     //All 所有元素都符合条件返回true 
 2             bool areAllAdmin = userList.All(u => u.RoleId == 1);   //所有用户的roleid都是1--->false
 3       //Any 有一个符合条件就返回true
 4             bool isAnyAdmin = userList.Any(u => u.RoleId == 1);//用户里有没有roleid为1的 --> true
 5       //Contains 包含返回true
 6             UserInfo user1=new UserInfo() { UId = 1, UserName = "zs", Age = 23, RoleId = 1 };
 7             //contains比较的是索引,所以就是list中有一个属性都相同的元素也会返回false,我们可以自定义一个比较类CompareUser来解决这个问题
 8             bool isContains = userList.Contains(user1);//s索引不同:false
 9             bool isContains2=userList.Contains(user1,new CompareUser());//自定义比较:true
10 
11 //自定义的userinfo比较器
12     public class CompareUser : IEqualityComparer<UserInfo>
13     { 
14         public bool Equals(UserInfo x, UserInfo y)
15         {
16             bool isSame = false;
17             //age,username,roleid相同,我们就认为是同一个userinfo
18             if (x.Age==y.Age&&x.UserName==y.UserName&&x.RoleId==y.RoleId)
19             {
20                 isSame=true;
21             }
22             return isSame;
23         }
24         public int GetHashCode(UserInfo obj)
25         {
26             throw new NotImplementedException();
27         }
28     }

6、聚合函数(Average,Count,Max,Min,Sum) 

 1   //平均年龄:28.8
 2             var avgAge = userList.Average(u => u.Age);
 3    //用户人数:5:  大于30岁的用户人数:2
 4             var userCount = userList.Count();
 5             var olduserCount = userList.Count(u => u.Age > 30);
 6    //最大年龄:42
 7             var maxAge = userList.Max(u => u.Age);
 8    //最小年龄:20
 9             var minAge = userList.Min(u => u.Age);
10    //年龄和:144
11             var sumAge = userList.Sum(u => u.Age);

7、元素操作符(ElementAt,Frist,Last,Singe和对应的xxxOrDefault)

    这些操作符加上OrDefault后缀后,在超出索引时不会抛出异常,而是返回一个默认值,(如:int返回0 ,引用类型返回null)

 1     //获取指定索引处的元素
 2             UserInfo user0 = userList.ElementAt(0);
 3             UserInfo user9 = userList.ElementAtOrDefault(9);
 4             //不报错,返回null,没有ordefault后缀会抛异常
 5        //获取第一个元素
 6             UserInfo userfrist = userList.First();
 7             UserInfo userfrist2 = userList.FirstOrDefault();
 8        //获取最后一个元素
 9             UserInfo userlast = userList.Last();
10             UserInfo userlast2 = userList.LastOrDefault();
11        //获取唯一元素()
12             UserInfo userSignal = userList.Single(u => u.Age < 21);
13             UserInfo userSignal2 = userList.SingleOrDefault(u => u.Age > 21);
         //报错,返回的元素不是唯一的

8、判断序列相等(SequenceEqual)

 1  //原始类型(字符串、int等,比较顺序和值,这两项都相等时返回true)
 2             IList<int> intList1 = new List<int> { 1, 2, 3, 4 };
 3             IList<int> intList2 = new List<int> { 2, 1, 3, 4 };
 4             //bool isEquel = intList1.SequenceEqual(intList2);
 5 
 6 //复杂类型(UserInfo,比较索引,索引相同返回true,可通过自定义比较器修改比较的规则)
 7             UserInfo user1 = new UserInfo() { UId = 1, UserName = "zs", Age = 23, RoleId = 1 };
 8             UserInfo user2 = new UserInfo() { UId = 1, UserName = "zs", Age = 23, RoleId = 1 };
 9             IList<UserInfo> list1 = new List<UserInfo>() { user1 };
10             IList<UserInfo> list2 = new List<UserInfo>() { user2};
11             //user1和user2的索引不同,返回false
12             bool isEquel = list1.SequenceEqual(list2);
13             //自定义比较器,只要属性都相等返回true
14             bool isEquel2 = list1.SequenceEqual(list2, new CompareUser());
15             
16 
17     //自定义的userinfo比较器
18     public class CompareUser : IEqualityComparer<UserInfo>
19     { 
20         public bool Equals(UserInfo x, UserInfo y)
21         {
22             bool isSame = false;
23             //age,username,roleid相同,我们就认为是同一个userinfo
24             if (x.Age==y.Age&&x.UserName==y.UserName&&x.RoleId==y.RoleId)
25             {
26                 isSame=true;
27             }
28             return isSame;
29         }
30         public int GetHashCode(UserInfo obj)
31         {
32             throw new NotImplementedException();
33         }
34     }

9、集合操作(Concat、Distinct、Except、Intersect、Union) 

 1      //合并 Concat
 2             IList<UserInfo> list1 = new List<UserInfo>() { user1,user2,user1 };
 3             IList<UserInfo> list2 = new List<UserInfo>() { user2 ,user2};
 4             var listConcat = list1.Concat(list2);
        //包含了user1,user2,user1,user2,user2 5 //去重 Distinct(差并交集会自动去重,去重和交差并集中的复杂类型也是根据索引来判断是否相同的,所以视情况自定义比较器) 6 var list4 = list1.Distinct();//user1,user2 7 //差集(list1中有,list中没有的) 8 var list5 = list1.Except(list2);//user1 9 //交集 10 var list6 = list1.Intersect(list2);//user2 11 //并集 12 var list7 = list1.Union(list2);//user1,user2

10、分区(Skip,SkipWhile,Take,TakeWhile)

1      //分区           
2             var resUsers = userList.Skip(2);//跳过前2条,返回从第3条到最后一条的记录
3             var resUsers2 = userList.SkipWhile(u => u.Age < 30); // 跳过满足条件的数据 
4             //结果:从年龄为33的开始,返回后几条
5 
6             var resTake = userList.Take(2);//取前2条数据
7             var resTake2 = userList.TakeWhile(u => u.Age >= 22);
8             //取满足条件的数据,如果连续几条都满足返回多条记录,直到某一条数据不满足条件  
9             //结果:返回第一条,如果把条件中22改成20,那么返回所有数据

11、类型转化(As,To,Cast)  select 默认返回的是IEnumerable类型

1        var users = from u in userList select u; //IEnumerable<UserInfo>
2             var usersEnum = (from u in userList select u).AsEnumerable<UserInfo>();//IEnumerable<UserInfo>
3             var usersCast = (from u in userList select u).Cast<UserInfo>();//IEnumerable<UserInfo>,功能和AsEnumerable一样,写着简单
4             var usersQuery = (from u in userList select u).AsQueryable<UserInfo>();//IQueryable<UserInfo>
5             var usersArray = (from u in userList select u).ToArray<UserInfo>();//UserInfo[]
6             var usersList = (from u in userList select u).ToList<UserInfo>();//List<UserInfo>
7             var usersDic = (from u in userList select u).ToDictionary<UserInfo,int>(u=>u.UId);//Dictionary<int,UserInfo>
posted @ 2018-05-17 22:04  捞月亮的猴子  阅读(3762)  评论(1编辑  收藏  举报