博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LINQ(集成化查询)
阅读量:6050 次
发布时间:2019-06-20

本文共 16902 字,大约阅读时间需要 56 分钟。

      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
item in res) { Console.WriteLine("--------- {0} --------", item.Key); // 取出该分组中的元素 foreach (string str in item) { Console.WriteLine(" {0}", str); } Console.WriteLine(); }

下面在看一例:

public class Student    {        ///         /// 学员ID        ///         public uint StuID { get; set; }        ///         /// 学员姓名        ///         public string StuName { get; set; }        ///         /// 课程        ///         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关键字来判断联合条件是否成立。

代码如下:

///     /// 图书分类信息    ///     public class Category    {        ///         /// 分别ID        ///         public int catID { get; set; }        ///         /// 分类名        ///         public string catName { get; set; }    }    ///     /// 图书信息    ///     public class BookInfo    {        ///         /// 图书ID        ///         public int BookID { get; set; }        ///         /// 书名        ///         public string BookName { get; set; }        ///         /// 图书所属分类的ID        ///         public int CateID { get; set; }    }
// 图书分类示例数据            List
bookCategs = new List
{ new Category { catID = 201, catName = "文学类" }, new Category { catID = 202, catName = "经济管理类" }, new Category { catID = 203, catName = "机械工程类" }, new Category { catID = 204, catName = "法律基础类" } }; // 图书信息示例数据 List
books = new List
{ 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     ///  12     /// 专辑信息 13     ///  14     public class Album 15     { 16         ///  17         /// 专辑名称 18         ///  19         public string Title { get; set; } 20         ///  21         /// 发行年份 22         ///  23         public int Year { get; set; } 24         ///  25         /// 专辑描述 26         ///  27         public string Description { get; set; } 28     } 29  30     ///  31     /// 曲目信息 32     ///  33     public class Track 34     { 35         ///  36         /// 曲目名称 37         ///  38         public string Name { get; set; } 39         ///  40         /// 艺术家名字 41         ///  42         public string Artist { get; set; } 43         ///  44         /// 所属专辑 45         ///  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
albums = new List
{ 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
tracks = new List
{ 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 g100 from a2 in g.DefaultIfEmpty(new Album { Title = "
<未知>
", Year = 0, Description = "
<无>
" })101 select new102 {103 TrackName = t.Name,104 Year = a2.Year,105 Artist = t.Artist,106 AlbumName = a2.Title,107 AlbumDesc = a2.Description108 };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     ///  11     /// 商品信息 12     ///  13     public class Goods 14     { 15         ///  16         /// 商品编号 17         ///  18         public string GsNo { get; set; } 19         ///  20         /// 商品名称 21         ///  22         public string GsName { get; set; } 23         ///  24         /// 商品单价 25         ///  26         public double GsPrice { get; set; } 27     } 28  29     ///  30     /// 销售单信息 31     ///  32     public class SalesOrder 33     { 34         ///  35         /// 单据ID 36         ///  37         public int OrderID { get; set; } 38         ///  39         /// 商品编号 40         ///  41         public string GoodsNo { get; set; } 42         ///  43         /// 销售时间 44         ///  45         public DateTime Time { get; set; } 46         ///  47         /// 销售数量 48         ///  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.GsPrice103                           };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查询是比较简单的,只要仔细,就不会出错的。。。。

 

转载于:https://www.cnblogs.com/czx1/p/4919200.html

你可能感兴趣的文章
服务器定义
查看>>
我的友情链接
查看>>
分布式系统的面试题15
查看>>
个人代码库の创建快捷方式
查看>>
由strcat函数引发的C语言中数组和指针问题的思考
查看>>
无锁编程
查看>>
如何在loadrunner中做关联
查看>>
max_element( )
查看>>
转: jquery中ajax回调函数使用this
查看>>
我的Java开发学习之旅------>Java 格式化类(java.util.Formatter)基本用法
查看>>
我的Android进阶之旅------>adbd cannot run as root in production builds 的解决方法
查看>>
Nginx http升级到https
查看>>
关于在RK3288上安装Opencv的方法
查看>>
7.Java集合-Arrays类实现原理及源码分析
查看>>
[POI2008]Triangles
查看>>
2016开发一个app需要多少钱?app开发需要哪些成本-app开发问题汇总-广州达到信息...
查看>>
程序找不到jvm的解决方法
查看>>
Java中Volatile的理解
查看>>
c++primer page 249 answer
查看>>
04单例模式Singleton
查看>>