那天有个小孩跟我说LINQ(二)

来源:互联网 发布:js的prototype是什么 编辑:程序博客网 时间:2024/05/01 01:57

小孩LINQ系列导航:(一)(二)(三)(四)(五)(六)(七)

1  LINQ TO Objects续(代码下载)

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

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

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

image

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace linq_Ch2.Entity
{
    public class Student
    {
        /// <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; }
        
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace linq_Ch2.Entity
{
    public class Classroom
    {
        /// <summary>
        /// 班级Id
        /// </summary>
        public int ClassId { get; set; }
        /// <summary>
        /// 班级名称
        /// </summary>
        public string ClassName { get; set; }
       
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace linq_Ch2.Entity
{
    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方法中写

  

   1:      List<Student> students = new List<Student> { 
   2:                  new Student{StuId=1,StuName="钱一",ClassId=1},
   3:                  new Student{StuId=2,StuName="赵二",ClassId=1},
   4:                  new Student{StuId=3,StuName="张三",ClassId=2},
   5:                  new Student{StuId=4,StuName="李四",ClassId=1},
   6:                  new Student{StuId=5,StuName="王五",ClassId=3},
   7:                  new Student{StuId=6,StuName="陈六",ClassId=2},
   8:                  new Student{StuId=7,StuName="田七",ClassId=3}
   9:              };
  10:              List<Score> scores = new List<Score> { 
  11:                  new Score{ScoreId=1,ItemName="语文",StuId=1,Scores=56},
  12:                  new Score{ScoreId=2,ItemName="语文",StuId=2,Scores=65},
  13:                  new Score{ScoreId=3,ItemName="语文",StuId=3,Scores=37},
  14:                  new Score{ScoreId=4,ItemName="数学",StuId=1,Scores=33},
  15:                  new Score{ScoreId=5,ItemName="数学",StuId=2,Scores=77},
  16:                  new Score{ScoreId=6,ItemName="数学",StuId=3,Scores=84},
  17:                  new Score{ScoreId=7,ItemName="英语",StuId=1,Scores=133},
  18:                  new Score{ScoreId=8,ItemName="英语",StuId=2,Scores=53},
  19:                  new Score{ScoreId=9,ItemName="英语",StuId=3,Scores=42},
  20:                  new Score{ScoreId=10,ItemName="英语",StuId=4,Scores=33},
  21:                  new Score{ScoreId=11,ItemName="数学",StuId=7,Scores=127}
  22:              };
  23:              List<Classroom> classrooms = new List<Classroom> { 
  24:                  new Classroom{ClassId=1,ClassName="高三(1)班"},
  25:                  new Classroom{ClassId=2,ClassName="高三(2)班"},
  26:                  new Classroom{ClassId=3,ClassName="高三(3)班"}
  27:              };

 

开始查询,用集合.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("学生姓名\t学科\t\t分数");
            foreach (var stu in query1)
            {
                Console.WriteLine(string.Format("{0}\t\t{1}\t\t{2}",stu.学生姓名,stu.学科,stu.分数));
            }

效果图

 

 

第二种方式:

   1:           var query2 = from a in students
   2:                           join b in scores
   3:                           on a.StuId equals b.StuId
   4:                           select new
   5:                           {
   6:                               学生姓名 = a.StuName,
   7:                               学科 = b.ItemName,
   8:                               分数 = b.Scores
   9:                           };
  10:   
  11:              Console.WriteLine("方式二");
  12:              Console.WriteLine("学生姓名\t学科\t\t分数");
  13:              foreach (var stu in query1)
  14:              {
  15:                  Console.WriteLine(string.Format("{0}\t\t{1}\t\t{2}", stu.学生姓名, stu.学科, stu.分数));
  16:              }

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

   1:   // 学生名  总分(如果分数表找不到,就算0分)
   2:              var query3 = from c in query2
   3:                           group c by c.学生姓名 into stuInfo
   4:                           select new
   5:                           {
   6:                               学生姓名 = stuInfo.Key,
   7:                               学生总分 = stuInfo.Sum(x => x.分数)
   8:                           };
   9:              Console.WriteLine("求总分的案例");
  10:              Console.WriteLine("学生姓名\t总分");
  11:              foreach (var stu in query3)
  12:              {
  13:                  Console.WriteLine(string.Format("{0}\t\t{1}", stu.学生姓名, stu.学生总分));
  14:              }

效果图:

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("学生姓名\t学科\t\t分数");
            foreach (var stu in query5)
            {
                Console.WriteLine(string.Format("{0}\t\t{1}\t\t{2}", stu.学生姓名, stu.学科, stu.分数));
            }

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

代码:

   1:   
   2:              Console.WriteLine("交叉查询方式");
   3:              var query6 = from a in students
   4:                           from b in scores
   5:                           select new
   6:                           {
   7:                               学生姓名 = a.StuName,
   8:                               学科 = b.ItemName,
   9:                               分数 = b.Scores
  10:                           };
  11:              Console.WriteLine("学生姓名\t学科\t\t分数");
  12:              foreach (var stu in query6)
  13:              {
  14:                  Console.WriteLine(string.Format("{0}\t\t{1}\t\t{2}", stu.学生姓名, stu.学科, stu.分数));
  15:              }

等同于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>

       

   1:       //SortList
   2:              SortedList<int, Student> users = new SortedList<int, Student>
   3:              {
   4:                         {2,new Student{StuId=2,StuName="钱一",ClassId=1}},
   5:                         {12,new Student{StuId=12,StuName="赵二",ClassId=1}},
   6:                         {1,new Student{StuId=1,StuName="张三",ClassId=2}},
   7:              };
   8:              Console.WriteLine("未按学生姓名排序前的结果如下:");
   9:              foreach (var item in users)
  10:              {
  11:                  Console.Write("     键"+item.Key + ":"+item.Value.StuName);
  12:              }
  13:              var query15 = from s in users
  14:                            orderby s.Value.StuName descending
  15:                            select s;
  16:              Console.WriteLine();
  17:              Console.WriteLine("按学生姓名排序后的结果如下:");
  18:              foreach (var item in query15)
  19:              {
  20:                  Console.Write("     键" + item.Key + ":" + item.Value.StuName);
  21:              }

效果图

image

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

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

image

效果图:

image

代码:

   1:             Console.WriteLine();
   2:              //LinkedList
   3:              LinkedList<int> ints2 = new LinkedList<int>();
   4:              ints2.AddFirst(0);
   5:              for (int i = 1; i < 10; i++)
   6:              {
   7:                  ints2.AddAfter(ints2.Find(i-1),i);
   8:              }
   9:              //使用Linq过滤,排序泛型双向链表
  10:              var query16 = from item in ints2
  11:                            where item > 0 && item < 9
  12:                            orderby item descending
  13:                            select item;
  14:              //显示结果
  15:              foreach (var item in query16)
  16:              {
  17:                  Console.Write(item.ToString()+",");
  18:              }

另一种方式:

   1:              Console.WriteLine();
   2:              var query17 = ints2.Where(x => x > 0 && x < 9).OrderByDescending(x => x);
   3:              //显示结果
   4:              foreach (var item in query16)
   5:              {
   6:                  Console.Write(item.ToString() + ",");
   7:              }

  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指定类型的基于集合的模型,泛型哈希集可以提供高性能的如并集,交集,补集等集合运算。泛型哈希集中的元素不能重复。泛型哈希集提供许多集合操作,如并集,交集,补集等。

      代码:

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

效果图:image

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

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

       代码:query9是一个Dictionary类型的

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

效果图:

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

原创粉丝点击