zoukankan      html  css  js  c++  java
  • 那天有个小孩跟我说LINQ(二)转载

    1  LINQ TO Objects续(代码下载)

         新建项目 linq_Ch2控制台程序,新建一个Entity文件夹

       1.1 学生成绩查询(练习Join)

            有三张表如下:学生表,班级表,成绩表。接下来我们按照这个在Entity文件夹建立3个实体类,类名跟表名一样。

    image

        public class StudentInfo
        {
            /// <summary>
            /// 学生编号
            /// </summary>
            public int StuId { get; set; }
    
            /// <summary>
            /// 学生姓名
            /// </summary>
            public string StuName { get; set; }
    
            /// <summary>
            /// 班级ID
            /// </summary>
            public int ClassId { get; set; }
    
            /// <summary>
            /// 班级
            /// </summary>
            public ClassRoom Classrooms { get; set; }
        }
     
        public class Classroom
        {
            /// <summary>
            /// 班级Id
            /// </summary>
            public int ClassId { get; set; }
    
            /// <summary>
            /// 班级名称
            /// </summary>
            public string ClassName { get; set; }
        }
        public class Score
        {
            /// <summary>
            /// 分数Id
            /// </summary>
            public int ScoreId { get; set; }
    
            /// <summary>
            /// 学科名称
            /// </summary>
            public string ItemName { get; set; }
    
            /// <summary>
            /// 学生ID
            /// </summary>
            public int StuId { get; set; }
    
            /// <summary>
            /// 学生
            /// </summary>
            public Student Students { get; set; }
    
            /// <summary>
            /// 分数
            /// </summary>
            public double Scores { get; set; }
        }

    如上,3个实体类创建好了

    ①查询出       学生名 学科  分数  3列信息

       首先我们初始化一点数据,在void main方法中写

    List<Student> students = new List<Student> { 
                     new Student{StuId=1,StuName="钱一",ClassId=1},
                     new Student{StuId=2,StuName="赵二",ClassId=1},
                     new Student{StuId=3,StuName="张三",ClassId=2},
                     new Student{StuId=4,StuName="李四",ClassId=1},
                     new Student{StuId=5,StuName="王五",ClassId=3},
                     new Student{StuId=6,StuName="陈六",ClassId=2},
                     new Student{StuId=7,StuName="田七",ClassId=3}
    
                  };
    
                List<Score> scores = new List<Score> { 
                     new Score{ScoreId=1,ItemName="语文",StuId=1,Scores=56},
                     new Score{ScoreId=2,ItemName="语文",StuId=2,Scores=65},
                     new Score{ScoreId=3,ItemName="语文",StuId=3,Scores=37},
                     new Score{ScoreId=4,ItemName="数学",StuId=1,Scores=33},
                     new Score{ScoreId=5,ItemName="数学",StuId=2,Scores=77},
                     new Score{ScoreId=6,ItemName="数学",StuId=3,Scores=84},
                     new Score{ScoreId=7,ItemName="英语",StuId=1,Scores=133},
                     new Score{ScoreId=8,ItemName="英语",StuId=2,Scores=53},
                     new Score{ScoreId=9,ItemName="英语",StuId=3,Scores=42},
                     new Score{ScoreId=10,ItemName="英语",StuId=4,Scores=33},
                     new Score{ScoreId=11,ItemName="数学",StuId=7,Scores=127}
    
                };
    
                List<ClassRoom> classrooms = new List<ClassRoom> { 
                     new ClassRoom{ClassId=1,ClassName="高三(1)班"},
                     new ClassRoom{ClassId=2,ClassName="高三(2)班"},
                     new ClassRoom{ClassId=3,ClassName="高三(3)班"}
    
                 };

    开始查询,用集合.Join(另一个集合,第一个集合的条件列,第二个集合的条件列,怎么处理(一个方法))

                //学生名 学科  分数
                var query1 = students.Join(
                    scores,                         //另一个集合
                    stu => stu.StuId,         //建立关系stu.StuId=sc.StuId
                    sc => sc.StuId,
                    (s, sc) => new
                    {           
                        //选出要的数据
                        学生姓名 = s.StuName,
                        学科 = sc.ItemName,
                        分数 = sc.Scores
                    }
                    );
    
                Console.WriteLine("学生姓名	学科		分数");
    
                foreach (var stu in query1)
                {
                    Console.WriteLine(string.Format("{0}		{1}		{2}", stu.学生姓名, stu.学科, stu.分数));
                }
    
                Console.ReadKey();

    效果图

     

    第二种方式:

                var query2 = from a in students
                             join b in scores
                             on a.StuId equals b.StuId
                             select new
                             {
                                  学生姓名 = a.StuName,
                                  学科 = b.ItemName,
                                  分数 = b.Scores
                              };
    
                Console.WriteLine("方式二");
                Console.WriteLine("学生姓名	学科		分数");
    
                foreach (var stu in query2)
                {
                    Console.WriteLine(string.Format("{0}		{1}		{2}", stu.学生姓名, stu.学科, stu.分数));
                }
    
                Console.ReadKey();

    ②算学生的总分,查出 学生名  总分

    // 学生名  总分(如果分数表找不到,就算0分)
                var query3 = from c in query2
                             group c by c.学生姓名 into stuInfo
                             select new
                            {
                               学生姓名 = stuInfo.Key,
                               学生总分 = stuInfo.Sum(x => x.分数)
                            };
    
                Console.WriteLine("求总分的案例");
                Console.WriteLine("学生姓名	总分");
    
                foreach (var stu in query3)
                {
                    Console.WriteLine(string.Format("{0}		{1}", stu.学生姓名, stu.学生总分));
                }

    效果图:

    image

    ③左查询(用join实现),DefaultIfEmpty后面括号中的参数是默认值,以students为主表,scores为副表,主表的信息全显示,副表只显示匹配学生Id相同的。

      (如果分数表找不到,就算0分)

    Console.WriteLine("左查询方式");
    
    var query5 = from a in students
            join b in scores
            on a.StuId equals b.StuId
            into pGroup
            from pItem in pGroup.DefaultIfEmpty(new Score { Scores = 0, ItemName = "没参考", StuId = a.StuId, ScoreId = 0 })
            select new
            {
              学生姓名 = a.StuName,
              学科 = pItem.ItemName,
              分数 = pItem.Scores
            };
    
    Console.WriteLine("学生姓名	学科		分数");
    
    foreach (var stu in query5)
    {
      Console.WriteLine(string.Format("{0}		{1}		{2}", stu.学生姓名, stu.学科, stu.分数));
    }
    
    Console.ReadKey();

    image

    效果图:

    image

    如果是数据库,则等同于SQL语句

    select s.StuId,s.StuName,s.ClassID,isnull(sc.ScoreId,0),isnull(sc.itemName,'没参考 '),isnull(sc.stuID,0),isnull(sc.score,0) from dbo.Student s left join dbo.Score sc on s.StuID=sc.stuID

    ④交叉查询

    效果图:

    image

    代码:

                Console.WriteLine("交叉查询方式");
                var query6 = from a in students
                             from b in scores
                             select new
                            {
                                学生姓名 = a.StuName,
                                学科 = b.ItemName,
                                分数 = b.Scores
                            };
    
                Console.WriteLine("学生姓名	学科		分数");
    
                foreach (var stu in query6)
                {
                    Console.WriteLine(string.Format("{0}		{1}		{2}", stu.学生姓名, stu.学科, stu.分数));
                }

    等同于SQL:

    select * from Student,Score

     1.2 类型转换操作

     ①将数据源转换为IEnumerable<T>类型,使用AsEnumerable<T>方法

    image

     将数据源转换为IQueryable<T>类型,使用AsQueryable<T>方法,用法同上

    ③将数据源转换成字典类型

       代码如下:

         //转换成Dictionary
        Dictionary<int, Student> query9 = students.ToDictionary(i => i.StuId);
        Console.WriteLine(query9[0].StuName);

     ④使用Enumerable类的Cast方法,该方法将非泛型的IEnumerable类型转换为泛型的IEnumerable<T>,至于转换成何种类型有Cast方法的TResult参数指定。

        例如:

       ArrayList arrList = new ArrayList();
      for (int i = 0; i < 100; i++)
      {
        arrList.Add(i.ToString());
      }
    
      var query10 = from i in arrList.Cast<string>()
              where i.IndexOf("0") > -1
              select i;
    
      foreach (var item in query10)
      {
        Console.Write(item+",");
      }
      Console.WriteLine();

    效果图:

    image

      ⑤使用 OfType<T> 筛选指定类型的元素

        代码如下:

      //OfType<T>
      ArrayList arrList2 = new ArrayList();
      arrList2.Add(1);
      arrList2.Add("茗洋");
      arrList2.Add("A");
      arrList2.Add(3);
      arrList2.Add("dd");
    
      var query11=from item in arrList2.OfType<string>()
              select item;
    
      foreach (var item in query11)
      {
        Console.Write(item+",");
      }
      Console.WriteLine();

    效果图:

    image

    ⑥将数据源转换为List<T>类型,使用ToList<T>()方法,用法同IQueryable<T>

    ⑦将数据源转换为数组类型,使用ToArray()方法,用法同IQueryable<T>

    ⑧转换为一对多的字典Lookup<TKey,TSource>,与Dictionary区别就是 相同key会对应多个值

       下面我们 把班级作为key列出来,然后列出班级里面的学生

    var query12 = from o in students
            join c in classrooms
            on o.ClassId equals c.ClassId
            select new Student
            {
              StuId = o.StuId,
              StuName = o.StuName,
              ClassId = o.ClassId,
              Classrooms = new ClassRoom{
                ClassId = c.ClassId,
                ClassName = c.ClassName
              }
            };

                ILookup<string, Student> query13 = query12.ToLookup(f => f.Classrooms.ClassName);

                foreach (var item in query13)
                {
                    Console.WriteLine(item.Key + "的学生如下");
                    foreach (var stu in item)
                    {
                        Console.Write(stu.StuName + ",");
                    }
                    Console.WriteLine();
                }

    效果图如下

    image

    1.3 操作集合

      1. 使用字符串的 EndsWith或者StartsWith过滤,使用CompareTo比较字符串的大小()

           例如:找出以“张”开头的学生姓名

    //StartWith
    var query14 = from o in query2
            where o.学生姓名.StartsWith("")
            select o;
    
    foreach (var item in query14)
    {
      Console.Write(item.学生姓名+",");
    }
    
    Console.WriteLine();

    效果图:

    image

    其中query2可以是 很多,例如List<T>,string[],IQueryable<T>等

      2. 操作泛型作排序列表SortList<TKey,TValue>

            SortList<TKey,TValue>表示按照键进行排序的键/值对的集合,键/值对是KeyValuePair<TKey,TValue>

           

    //SortList
    SortedList<int, Student> users = new SortedList<int, Student>
    {
      {2,new Student{StuId=2,StuName="钱一",ClassId=1}},
      {12,new Student{StuId=12,StuName="赵二",ClassId=1}},
      {1,new Student{StuId=1,StuName="张三",ClassId=2}},
    };

    Console.WriteLine("未按学生姓名排序前的结果如下:");

    foreach (var item in users)
    {
      Console.Write("     键" + item.Key + ":" + item.Value.StuName);
    }

    var query15 = from s in users
            orderby s.Value.StuName descending
            select s;

    Console.WriteLine();

    Console.WriteLine("按学生姓名排序后的结果如下:");

    foreach (var item in query15)
    {
      Console.Write("     键" + item.Key + ":" + item.Value.StuName);
    }

    Console.ReadKey();

    效果图

    image

      3. 操作泛型双向链表LinkedList<T>

           泛型双向列表LinkedList<T>表示由T指定类型的双向链表,它通过当前元素可以直接访问该元素的前一个或者后一个元素(如果不存在返回空),元素为LinkedListNode<T>类型

    image

    效果图:

    image

    代码:

      Console.WriteLine();
    
      //LinkedList
      LinkedList<int> ints2 = new LinkedList<int>();
      ints2.AddFirst(0);
    
      for (int i = 1; i < 10; i++)
      {
        ints2.AddAfter(ints2.Find(i - 1), i);
      }
    
      //使用Linq过滤,排序泛型双向链表
      var query16 = from item in ints2
              where item > 0 && item < 9
              orderby item descending
              select item;
      //显示结果
      foreach (var item in query16)
      {
        Console.Write(item.ToString() + ",");
      }

    另一种方式:

      Console.WriteLine();
      var query17 = ints2.Where(x => x > 0 && x < 9).OrderByDescending(x => x);
      //显示结果
      foreach (var item in query17)
      {
        Console.Write(item.ToString() + ",");
      }

      4. 操作泛型队列Queue<T>

            先进先出的线性表,使用Enqueue方法进行元素入队(添加)操作,使用Dequeue方法进行元素出队(删除)操作;使用Clear方法进行清空队列 操作。Queue类没有实现IEnumerable<T>接口或IEnumerable接口,所以不能使用LINQ直接操作Queue类型的 对象,可以使用Queue对象的Cast方法先把它转换为IEnumerable<T>类型,然后在使用LINQ对齐操作

      Console.WriteLine();
      Queue<Student> queues = new Queue<Student>();
      queues.Enqueue(new Student { StuId=11,StuName="大一",ClassId=1});
      queues.Enqueue(new Student { StuId = 2, StuName = "大二", ClassId = 1 });
      queues.Enqueue(new Student { StuId = 34, StuName = "大三", ClassId = 2 });
      queues.Enqueue(new Student { StuId = 4, StuName = "大四", ClassId = 1 });
      var query18 = queues.OrderByDescending(x=>x.StuId);
    
      //显示结果
      foreach (var item in query18)
      {
        Console.Write(item.StuName + ",");
      }

    效果图:image

    如果是Queue先转换成IEnumerable<T>,在LINQ操作

     5. 操作泛型堆栈Stack<T>

          后进先 出的线性表,使用Push方法进行元素入栈(添加)操作,使用Dequeue方法进行元素出栈(删除)操作;使用Clear方法进行清空堆栈操作。 Stack类没有实现IEnumerable<T>接口或IEnumerable接口,所以不能使用LINQ直接操作Queue类型的对象, 可以使用Stack对象的Cast方法先把它转换为IEnumerable<T>类型,然后在使用LINQ对齐操作

    效果图:image

    代码:

      Console.WriteLine();
      Stack<Student> stacks = new Stack<Student>();
      stacks.Push(new Student { StuId = 11, StuName = "大一", ClassId = 1 });
      stacks.Push(new Student { StuId = 2, StuName = "大二", ClassId = 1 });
      stacks.Push(new Student { StuId = 34, StuName = "大三", ClassId = 2 });
      stacks.Push(new Student { StuId = 4, StuName = "大四", ClassId = 1 });
      var query19 = from s in stacks
              where s.ClassId != 1 || s.StuId!=2
              select s;
    
      //显示结果
      foreach (var item in query19)
      {
        Console.Write(item.StuName + ",");
      } 

     6. 操作泛型哈希集HashSet<T>

          后泛型哈希集HashSet<T>是由T指定类型的基于集合的模型,泛型哈希集可以提供高性能的如并集,交集,补集等集合运算。泛型哈希集中的元素不能重复。泛型哈希集提供许多集合操作,如并集,交集,补集等。

          代码:

      /*HashSet*/
      Console.WriteLine();
      HashSet<Student> hashsets = new HashSet<Student> { 
        new Student{StuId=1,StuName="钱一",ClassId=1},
        new Student{StuId=2,StuName="赵二",ClassId=1},
        new Student{StuId=3,StuName="张三",ClassId=2},
        new Student{StuId=4,StuName="李四",ClassId=1},
        new Student{StuId=5,StuName="王五",ClassId=3},
        new Student{StuId=6,StuName="陈六",ClassId=2},
        new Student{StuId=7,StuName="田七",ClassId=3}
      };
    
      hashsets.Add(new Student { StuId = 11, StuName = "大一", ClassId = 1 });
      //先按班级升序排序,再按姓名降序
      var query20 = from s in hashsets
              orderby s.ClassId ascending, s.StuName descending
              select s;
    
      //显示结果
      foreach (var item in query20)
      {
        Console.Write(item.StuName + ",");
      }

    效果图:image

       7. 操作泛型字典Dictionary<TKey,TValue> 

           键不能重复,值可重复,键不会自动排序

           代码:query9是一个Dictionary类型的

      Console.WriteLine();
      var query21 = from o in query9
              where o.Value.StuName.CompareTo("") > 0 //学生姓名大于“张”
              orderby o.Key
              select o;
    
      foreach (var item in query21)
      {
        Console.WriteLine(item.Key + ":"+item.Value.StuName);
      }

    效果图:

    image

        8. 操作泛型排序字典SortedDictionary<TKey,TValue> 

             与Dictionary<TKey,TValue>的区别:泛型排序字典对添加的元素自动按进行排序,代码例如:SortDictionary<int,Student> c=new SortDictionary<int,Student>{…….}

       9. 操作泛型通用集合Collection<T>,跟List<T>一样用就行了

       10. 操作泛型绑定列表 BindingList<T>

               泛型绑定列表BindingList<T>能够提供支持数据绑定的泛型集合,他提供了IBindingList接口的具体泛型实现,可以用作创建双向数据绑定机制的积累,还可以通过AddNew方法支持创建实例

    跟List<T>一样用就行了

    关于还剩一点linq to objects明天写,顺便带点Linq to SQL

  • 相关阅读:
    在Docker中安装JDK
    在Docker中安装Zookeeper以及集群环境搭建
    Druid连接池加密
    在Docker中安装Nginx
    Docker镜像、容器、仓库的介绍
    记一次 oracle 流复制 传播进程故障
    今天遭遇 cannot restore segment prot after reloc:Permission denied
    记一次由raid换盘引起的message记录
    今晚测试了下微信的摇一摇传图
    遭遇linux 异常掉电后 文件系统只读
  • 原文地址:https://www.cnblogs.com/kloseking/p/3168029.html
Copyright © 2011-2022 走看看