• LINQ(集成化查询)


          LINQ可以对数组、集合等数据结构进行查询、筛选、排序等操作;也可以用于与数据库交互;也支持对XML的操作,使用LINQ技术可以动态创建、筛选和修改XML数据和直接操作XML文件。

    一). LINQ基本语法:

          (1)所有的LINQ查询表达式都是以from....in....开头;

          (2)以select或group子句结束。以select子句结束表示从数据源序列筛选出元素;以group子句结束表示将从数据源序列中筛选出来的元素进行分组,并把每个分组放进查询结果集中。

    例如:var result=from str in list select str;

             var result from str in list group s by str[0];   

    ).延迟执行与强制立即执行

       先看以下代码:var result=from str in list select str;当执行上述代码时,LINQ查询实际上并未执行,而是仅仅把用于查询的“命令”存放在result变量中,只到执行到遍历访问代码时才会执行查询:foreach(var a in result){。。。。。},这就是延迟执行。当然,可以调用Count,ToList,ToArray等方法来时查询立即执行,即使LINQ查询强行立即执行。

    三).筛选、排序、分组

    (1)在查询语句中,用where子句来设定筛选条件(一个或多个条件),如果where子句后面条件为真,则符合条件;若为假,则不符合条件。

    例如:var a=from b in c where b>10 select b;

    (2)对查询结果重新排序可以用orderby子句,默认情况下按升序排序,如果要进行降序排序,就必须在orderby子句后加上descending关键字。

    例如:var a=from b in c orderby b select b;

    (3)对数据进行分组要有分组依据,因此group一般与by关键字连用,格式如下:group <要进行分组的元素>by<分组依据>

    如果要对分组的数据进行操作,可以在查询语句中储存个分组的数据,即在分组语句后面接上into关键字。如:group emp by emp.Department into eg;数据分组后会将每个分量都存入eg变量中,随后可以用select子句把存放在eg中的分组选择进行结果中。如下:group emp by emp.Department into eg select eg;这时候查询结果中的每个元素都是IGrouping<TKey,TElement>类型的对象,IGrouping<TKey,TElement>带了2个类型参数,TKey表示分组依据(Key)的类型,TElement表示每个分组中元素的类型,由于IGrouping接口继承自IEnumerable<out T>接口,因此,只要使用foreach循环就可以访问分组中的元素。

                // 示例数据源
                string[] arr = { "table", "use", "up", "take", "turn", "reset", "remove", "we", "wave", "work", "word" };
    
                // 查询数据源中的所有元素
                // 并以首字母作为分组依据
                var res = from s in arr
                          group s by s.ToUpper()[0];
                // 输出查询结果
                Console.WriteLine("共有{0}个分组。", res.Count());
                foreach (IGrouping<char, string> item in res)
                {
                    Console.WriteLine("--------- {0} --------", item.Key);
                    // 取出该分组中的元素
                    foreach (string str in item)
                    {
                        Console.WriteLine("  {0}", str);
                    }
                    Console.WriteLine();
                }

    下面在看一例:

    public class Student
        {
            /// <summary>
            /// 学员ID
            /// </summary>
            public uint StuID { get; set; }
            /// <summary>
            /// 学员姓名
            /// </summary>
            public string StuName { get; set; }
            /// <summary>
            /// 课程
            /// </summary>
            public string Course { get; set; }
        }
                Student[] students =
                {
                    new Student { StuID = 1, StuName = "小陈", Course = "C++基础" },
                    new Student { StuID = 2, StuName = "小林", Course = "VB入门" },
                    new Student { StuID = 3, StuName = "小邓", Course = "C++基础" },
                    new Student { StuID = 4, StuName = "小李", Course = "C#客户端开发" },
                    new Student { StuID = 5, StuName = "小唐", Course = "C++基础" },
                    new Student { StuID = 6, StuName = "小周", Course = "VB入门" },
                    new Student { StuID = 7, StuName = "小张", Course = "VB入门" },
                    new Student { StuID = 8, StuName = "小吴", Course = "C#客户端开发" },
                    new Student { StuID = 9, StuName = "小孙", Course = "C++基础" },
                    new Student { StuID = 10, StuName = "小孟", Course = "C#客户端开发" }
                };
                // 筛选出学号大于5的学员
                // 并按课程进行分组
                // 学号按降序排列
                var res = from s in students
                      orderby s.StuID descending
                      where s.StuID > 5
                      group s by s.Course into g
                      select g;
                foreach (var g in res)
                {
                    Console.WriteLine("----- {0} -----", g.Key);
                    foreach (Student stu in g)
                    {
                        Console.WriteLine("学号:{0},姓名:{1},课程:{2}", stu.StuID, stu.StuName, stu.Course);
                    }
                    Console.WriteLine();
                }

    四).复杂查询

    (1)动态创建类型

    在比较复杂的查询中,查询结果通常会生成一个新的类型,以使其内部包含来自多个数据序列的属性。许多时候,这些新类型并不是固定的,不同的查询需求会产生不同的结果,如果为每种查询结果都去定义相应的类,那有可能变得很复杂,面对这种情况,使用动态类型是较理想的选择。动态类型无需事先去定义类,即可根据代码上下文的需要动态地去创建新类型,实现方法是运用new运算符,创建的新类型并没有确切的名称,是由编译器自动分配的,因此在声明量时应使用var关键字,由编译器自动去识别其类型。

    例如:

                var a = new
                {
                    b = "cajj",
                    c = 123
                };
                Console.WriteLine("{0}    {1}", a.b, a.c);

    也可以使用dynamic关键字来声明用于引用匿名类型的变量。使用dynamic声明的变量属于动态类型,在编译阶段不进行解析,只在运行时动态解析。

    例如:

    dynamic b = new
                {
                    Name = "Java",
                    Age = 18,
                    Birth = new DateTime(1997, 07, 06)
                };
                Console.WriteLine("Name={0}   Age={1}   Birth={2:yyyy-M-d}", b.Name, b.Age, b.Birth);

    (2)联合查询

    联合查询主要通过jion关键字来完成的。所谓的联合查询,可以理解为联合多个数据序列进行查询,并从中返回查询结果。查询结果中的数据可能来自于多个数据序列。多个数据序列要进行联合,需要提供一个联合条件才能使多个序列完成正确的联合,所以,jion关键字后面紧跟着on关键字,并通过equals关键字来判断联合条件是否成立。

    代码如下:

        /// <summary>
        /// 图书分类信息
        /// </summary>
        public class Category
        {
            /// <summary>
            /// 分别ID
            /// </summary>
            public int catID { get; set; }
            /// <summary>
            /// 分类名
            /// </summary>
            public string catName { get; set; }
        }
    
        /// <summary>
        /// 图书信息
        /// </summary>
        public class BookInfo
        {
            /// <summary>
            /// 图书ID
            /// </summary>
            public int BookID { get; set; }
            /// <summary>
            /// 书名
            /// </summary>
            public string BookName { get; set; }
            /// <summary>
            /// 图书所属分类的ID
            /// </summary>
            public int CateID { get; set; }
        }
                // 图书分类示例数据
                List<Category> bookCategs = new List<Category>
                {
                    new Category { catID = 201, catName = "文学类" },
                    new Category { catID = 202, catName = "经济管理类" },
                    new Category { catID = 203, catName = "机械工程类" },
                    new Category { catID = 204, catName = "法律基础类" }
                };
    
                // 图书信息示例数据
                List<BookInfo> books = new List<BookInfo>
                {
                    new BookInfo { BookID = 1, BookName = "图书01", CateID = 202 },
                    new BookInfo { BookID = 2, BookName = "图书02",CateID = 204 },
                    new BookInfo { BookID = 3, BookName = "图书03", CateID = 201 },
                    new BookInfo { BookID = 4, BookName = "图书04", CateID = 202 },
                    new BookInfo { BookID = 5, BookName = "图书05",CateID = 204 },
                    new BookInfo { BookID = 6, BookName = "图书06", CateID = 204 },
                    new BookInfo { BookID = 7, BookName = "图书07", CateID = 203 },
                    new BookInfo { BookID = 8, BookName = "图书08",CateID = 202 },
                    new BookInfo { BookID = 9, BookName = "图书09", CateID = 203 },
                    new BookInfo { BookID = 10, BookName = "图书10", CateID = 202 },
                    new BookInfo { BookID = 11, BookName = "图书11", CateID = 201 },
                    new BookInfo { BookID = 12, BookName = "图书12", CateID = 203 },
                    new BookInfo { BookID = 13, BookName = "图书13", CateID = 201 },
                    new BookInfo { BookID = 14, BookName = "图书14", CateID = 204 },
                    new BookInfo { BookID = 15, BookName = "图书15", CateID = 203 },
                    new BookInfo { BookID = 16, BookName = "图书16", CateID = 202 },
                };

    接下来,联合books和bookCategs两个数据序列,代码如下:

                // 联合查询,并产生新的类型
                var qryres = from b in books
                             join c in bookCategs on b.CateID equals c.catID
                             select new
                             {
                                 b.BookName,
                                 c.catName
                             };
                // 输出结果
                foreach (var bitem in qryres)
                {
                    Console.WriteLine("图书名:{0},所属分类:{1}", bitem.BookName, bitem.catName);
                }

    上述代码,select子句使用new运算符动态创建匿名类型,并使用BookInfo对象的BookName属性和Category对象的catName属性作为新类型的属性,也就是说,创建的匿名类型具有BookName和catName两个属性,当然,也可以为动态创建的匿名类型使用自己命名的属性名,代码如下:

                var qryres2 =
                    from bk in books
                    join bc in bookCategs on bk.CateID equals bc.catID
                    select new
                        {
                            Book_ID = bk.BookID,
                            Book_Name = bk.BookName,
                            Book_Cate = bc.catName
                        };
                // 输出结果
                foreach (var bk in qryres2)
                {
                    Console.WriteLine("图书ID:{0},图书名:{1},所属分类:{2}", bk.Book_ID, bk.Book_Name, bk.Book_Cate);
                }

    在上面的例子中,与每个BookInfo对象实例的CateID属性相对应的Category对象都能在bookCategs列表中找到,这种的联合查询称为”内部联合“。下面,就考虑另一种情况,即当序列A与序列B进行联合查询时,在序列B中找不到与序列A的项匹配的元素。

    代码如下:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 namespace My
      8 {
      9 
     10     #region 定义类型
     11     /// <summary>
     12     /// 专辑信息
     13     /// </summary>
     14     public class Album
     15     {
     16         /// <summary>
     17         /// 专辑名称
     18         /// </summary>
     19         public string Title { get; set; }
     20         /// <summary>
     21         /// 发行年份
     22         /// </summary>
     23         public int Year { get; set; }
     24         /// <summary>
     25         /// 专辑描述
     26         /// </summary>
     27         public string Description { get; set; }
     28     }
     29 
     30     /// <summary>
     31     /// 曲目信息
     32     /// </summary>
     33     public class Track
     34     {
     35         /// <summary>
     36         /// 曲目名称
     37         /// </summary>
     38         public string Name { get; set; }
     39         /// <summary>
     40         /// 艺术家名字
     41         /// </summary>
     42         public string Artist { get; set; }
     43         /// <summary>
     44         /// 所属专辑
     45         /// </summary>
     46         public Album AlbumOf { get; set; }
     47     }
     48     #endregion
     49 
     50     class Program
     51     {
     52         static void Main(string[] args)
     53         {
     54             // 专辑列表
     55             Album album1 = new Album { Title = "专辑 1", Year = 2003, Description = "这是第一张专辑。" };
     56             Album album2 = new Album { Title = "专辑 2", Year = 2009, Description = "这是第二张专辑。" };
     57             List<Album> albums = new List<Album> { album1, album2 };
     58 
     59             // 曲目列表
     60             Track track1 = new Track { Name = "曲目 1", Artist = "艺术家 1", AlbumOf = album1 };
     61             Track track2 = new Track { Name = "曲目 2", Artist = "艺术家 2", AlbumOf = album2 };
     62             Track track3 = new Track { Name = "曲目 3", Artist = "艺术家 3", AlbumOf = album2 };
     63             Track track4 = new Track { Name = "曲目 4", Artist = "艺术家 4", AlbumOf = album1 };
     64             Track track5 = new Track { Name = "曲目 5", Artist = "艺术家 5", AlbumOf = album2 };
     65             Track track6 = new Track { Name = "曲目 6", Artist = "艺术家 6", AlbumOf = null };
     66             List<Track> tracks = new List<Track> { track1, track2, track3, track4, track5, track6 };
     67 
     68             // 开始查询
     69             var res1 = from t in tracks
     70                        join a in albums on t.AlbumOf equals a into g1
     71                        from a1 in g1.DefaultIfEmpty()
     72                        select new
     73                        {
     74                            TrackName = t.Name,
     75                            Artist = t.Artist,
     76                            AlbumName = a1 == null ? "未知专辑" : a1.Title
     77                        };
     78 
     79             // 以下代码会发生异常
     80             //var res1 = from t in tracks
     81             //           join a in albums on t.AlbumOf equals a into g1
     82             //           from a1 in g1.DefaultIfEmpty()
     83             //           select new
     84             //           {
     85             //               TrackName = t.Name,
     86             //               Artist = t.Artist,
     87             //               AlbumName = a1.Title
     88             //           };
     89 
     90             // 输出结果
     91             foreach (var item in res1)
     92             {
     93                 Console.WriteLine("曲目:{0},艺术家:{1},专辑:{2}", item.TrackName, item.Artist, item.AlbumName);
     94             }
     95 
     96             Console.WriteLine();
     97 
     98             var res2 = from t in tracks
     99                        join a in albums on t.AlbumOf equals a into g
    100                        from a2 in g.DefaultIfEmpty(new Album { Title = "<未知>", Year = 0, Description = "<无>" })
    101                        select new
    102                            {
    103                                TrackName = t.Name,
    104                                Year = a2.Year,
    105                                Artist = t.Artist,
    106                                AlbumName = a2.Title,
    107                                AlbumDesc = a2.Description
    108                            };
    109             // 输出结果
    110             foreach (var item in res2)
    111             {
    112                 Console.WriteLine("曲目:{0},年份:{1},艺术家:{2},专辑:{3},专辑描述:{4}", item.TrackName, item.Year, item.Artist, item.AlbumName, item.AlbumDesc);
    113             }
    114 
    115             Console.Read();
    116         }
    117     }
    118 }

    (3) 嵌套查询

    嵌套查询是指在一个查询内部嵌套这另一个查询,其实嵌套查询是比较简单的,就直接看个例子吧。

    代码如下:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 namespace My
      8 {
      9     #region 定义类型
     10     /// <summary>
     11     /// 商品信息
     12     /// </summary>
     13     public class Goods
     14     {
     15         /// <summary>
     16         /// 商品编号
     17         /// </summary>
     18         public string GsNo { get; set; }
     19         /// <summary>
     20         /// 商品名称
     21         /// </summary>
     22         public string GsName { get; set; }
     23         /// <summary>
     24         /// 商品单价
     25         /// </summary>
     26         public double GsPrice { get; set; }
     27     }
     28 
     29     /// <summary>
     30     /// 销售单信息
     31     /// </summary>
     32     public class SalesOrder
     33     {
     34         /// <summary>
     35         /// 单据ID
     36         /// </summary>
     37         public int OrderID { get; set; }
     38         /// <summary>
     39         /// 商品编号
     40         /// </summary>
     41         public string GoodsNo { get; set; }
     42         /// <summary>
     43         /// 销售时间
     44         /// </summary>
     45         public DateTime Time { get; set; }
     46         /// <summary>
     47         /// 销售数量
     48         /// </summary>
     49         public int Qty { get; set; }
     50     }
     51     #endregion
     52 
     53     class Program
     54     {
     55         static void Main(string[] args)
     56         {
     57             // 商品信息 - 示例数据
     58             Goods[] goodsArr = 
     59             {
     60                 new Goods { GsNo = "G-1", GsName = "报纸", GsPrice = 1.50d },
     61                 new Goods { GsNo = "G-2", GsName = "食盐", GsPrice = 3.65d },
     62                 new Goods { GsNo = "G-3", GsName = "火柴", GsPrice = 0.50d },
     63                 new Goods { GsNo = "G-4", GsName = "灯泡", GsPrice = 12.30d },
     64                 new Goods { GsNo = "G-5", GsName = "剪刀", GsPrice = 4.50d }
     65             };
     66 
     67             // 销售单据 - 示例数据
     68             SalesOrder[] orders =
     69             {
     70                 new SalesOrder { OrderID = 1, GoodsNo = goodsArr[0].GsNo, Qty = 3, Time = new DateTime(2014, 1, 2) },
     71                 new SalesOrder { OrderID = 2, GoodsNo = goodsArr[1].GsNo, Qty = 5, Time = new DateTime(2014, 1, 4) },
     72                 new SalesOrder { OrderID = 3, GoodsNo = goodsArr[2].GsNo, Qty = 2, Time = new DateTime(2014, 1, 12) },
     73                 new SalesOrder { OrderID = 4, GoodsNo = goodsArr[3].GsNo, Qty = 6, Time = new DateTime(2014, 1, 20) },
     74                 new SalesOrder { OrderID = 5, GoodsNo = goodsArr[4].GsNo, Qty = 1, Time = new DateTime(2014, 2, 3) },
     75                 new SalesOrder { OrderID = 6, GoodsNo = goodsArr[2].GsNo, Qty = 4, Time = new DateTime(2014, 2, 9) },
     76                 new SalesOrder { OrderID = 7, GoodsNo = goodsArr[1].GsNo, Qty = 8, Time = new DateTime(2014, 3, 13) },
     77                 new SalesOrder { OrderID = 8, GoodsNo = goodsArr[3].GsNo, Qty = 10, Time = new DateTime(2014, 3, 11) },
     78                 new SalesOrder { OrderID = 9, GoodsNo = goodsArr[0].GsNo, Qty = 15, Time = new DateTime(2014, 3, 18) },
     79                 new SalesOrder { OrderID = 10, GoodsNo = goodsArr[0].GsNo, Qty = 7, Time = new DateTime(2014, 2, 22) },
     80                 new SalesOrder { OrderID = 11, GoodsNo = goodsArr[3].GsNo, Qty = 20, Time = new DateTime(2014, 3, 17) },
     81                 new SalesOrder { OrderID = 12, GoodsNo = goodsArr[1].GsNo, Qty = 13, Time = new DateTime(2014, 1, 29) },
     82                 new SalesOrder { OrderID = 13, GoodsNo = goodsArr[2].GsNo, Qty = 8, Time = new DateTime(2014, 2, 9) },
     83                 new SalesOrder { OrderID = 14, GoodsNo = goodsArr[4].GsNo, Qty = 21, Time = new DateTime(2014, 3, 16) },
     84                 new SalesOrder { OrderID = 15, GoodsNo = goodsArr[2].GsNo, Qty = 6, Time = new DateTime(2014, 2, 15) }
     85             };
     86 
     87             /*
     88              * 查询并计算出各个商品的
     89              * 总销售额
     90              */
     91             var res = from g in goodsArr
     92                       let totalQty =
     93                       /* 以下为嵌套查询 */
     94                       (from od in orders
     95                        where od.GoodsNo == g.GsNo
     96                        select od).Sum(odr => odr.Qty)
     97                       select new
     98                           {
     99                               g.GsNo,
    100                               g.GsName,
    101                               /* 计算总销售额 */
    102                               Total = totalQty * g.GsPrice
    103                           };
    104 
    105             // 输出查询结果
    106             foreach (var item in res)
    107             {
    108                 Console.WriteLine("编号:{0},商品:{1},总额:{2:N2}", item.GsNo, item.GsName, item.Total);
    109             }
    110 
    111             Console.Read();
    112         }
    113     }
    114 }

    博客写到这,可以看到其实LINQ查询是比较简单的,只要仔细,就不会出错的。。。。

  • 相关阅读:
    RabbitMq windows 安装
    JQuery.Ajax()的data参数传递方式
    [转载]ASP.NET中TextBox控件设立ReadOnly="true"后台取不到值
    vue-cli 3.0脚手架搭建项目
    二、操作符
    一、JavaScript基础
    html苹方字体
    js十大排序算法收藏
    iframe高度自适应的6个方法
    CSS3:不可思议的border属性
  • 原文地址:https://www.cnblogs.com/czx1/p/4919200.html
Copyright © 2020-2023  润新知