zoukankan      html  css  js  c++  java
  • 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查询是比较简单的,只要仔细,就不会出错的。。。。

  • 相关阅读:
    蓝桥网试题 java 基础练习 特殊的数字
    蓝桥网试题 java 基础练习 杨辉三角形
    蓝桥网试题 java 基础练习 查找整数
    蓝桥网试题 java 基础练习 数列特征
    蓝桥网试题 java 基础练习 字母图形
    蓝桥网试题 java 基础练习 01字串
    蓝桥网试题 java 基础练习 回文数
    蓝桥网试题 java 基础练习 特殊回文数
    Using text search in Web page with Sikuli
    each of which 用法
  • 原文地址:https://www.cnblogs.com/czx1/p/4919200.html
Copyright © 2011-2022 走看看