c# Linq查询详解
c#提供的ling查询极大的遍历了集合的查询过程,且使用简单方便,非常的有用。
下面将分别用简单的例子说明:ling基本查询、延迟查询属性、类型筛选、复合from字句、多级排序、分组查询、联合查询、合并、分页、聚合操作符、并行linq、取消长时间运行的并行ling查询。
Lambda表达式简介:
/*Lambda表达式:Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数 表达式位于 => 运算符右侧的 lambda 表达式称为“表达式 lambda”。 * (input parameters) => expression * 示例:*/ delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //最后j = 25 }
基本查询
语句:
var query = from r in listStudents where r.score < 60 orderby r.score descending select r; //var q2 = listStudents.Where(r => r.score < 60).OrderByDescending(r => r.score).Select(r => r) ;//或使用Lambda表达式
例子:
/// <summary> /// 学生结构体 /// </summary> struct Student { /// <summary> /// 姓名 /// </summary> public string name; /// <summary> /// 年龄 /// </summary> public int age; /// <summary> /// 班号 /// </summary> public int grade; /// <summary> /// 分数 /// </summary> public float score; } /// <summary> /// linq /// 基本查询 /// </summary> static void Linq1() { #region 构造查询数据 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孙xxx"; break; case 4: name = "钱xxx"; break; default: name = "赵xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion //从50个学生中选择出不及格的人员名单并按分数降序排列 var query = from r in listStudents where r.score < 60 orderby r.score descending select r; //var q2 = listStudents.Where(r => r.score < 60).OrderByDescending(r => r.score).Select(r => r) ;//或使用Lambda表达式 //orderby升序即从小到大,orderby r.score descending降序即从大到小 Console.WriteLine("不及格的人员名单:"); foreach (Student st in query) { Console.WriteLine("***************"); Console.WriteLine("姓名:"+st.name); Console.WriteLine("班级:"+st.grade); Console.WriteLine("年龄:"+st.age); Console.WriteLine("分数:"+st.score); } Console.ReadKey(); }
延迟查询属性
linq查询为延迟查询,只需构造一次查询语句,可以多次使用。
例子:
/// <summary> /// Linq /// 延迟查询 /// linq查询为延迟查询,只需构造一次查询语句,可以多次使用 /// </summary> static void Linq2() { #region 构造查询数据 List<string> lists = new List<string> { "Jack","Pet","Hant","Li","Kkk"}; #endregion var query = from r in lists where r.StartsWith("J") select r; Console.WriteLine("第一次查询结果:"); foreach (string st in query) { Console.WriteLine( st); } Console.WriteLine("第二次查询结果:"); lists.Add("Jone"); lists.Add("Jimi"); lists.Add("Johu"); foreach (string st in query) { Console.WriteLine(st); } Console.ReadKey(); /* 输出结果: * 第一次:Jack * 第二次:Jack Jone Jimi Johu */ }
类型筛选
利用OfType方法可以把特定类型数据筛选出来。
例子
/// <summary> /// Linq类型筛选-ofType /// </summary> static void Linq3() { object[] pList = new object[] { 1,"one",2,"two",3,"three"}; var query = pList.OfType<string>(); foreach (var st in query) { Console.WriteLine(st); } Console.ReadKey(); /* 输出结果: * one two three */ }
复合from子句
语句:
var query = from s in listStudents from n in s.name where n == '赵' orderby s.score descending select s.grade + "班-" + s.name + ",分数" + +s.score; /*查询出所有姓赵的学生的班级、姓名、分数信息,并按分数由高到低排序*/
例子:
/// <summary> /// linq复合from字句 /// </summary> static void Linq4() { #region 构造查询数据 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孙xxx"; break; case 4: name = "钱xxx"; break; default: name = "赵xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion var query = from s in listStudents from n in s.name where n == '赵' orderby s.score descending select s.grade + "班-" + s.name + ",分数" + +s.score; /*查询出所有姓赵的学生的班级、姓名、分数信息,并按分数由高到低排序*/ foreach (var t in query) { Console.WriteLine(t); } Console.ReadKey(); }
多级排序
语句:
//参数越靠前,优先级越高 //先按score排序,当分数相同时再按grade排序...依次类推 var query = from s in listStudents orderby s.score, s.grade, s.age, s.name select s;
例子:
/// <summary> /// 多级排序 /// </summary> static void Linq5() { #region 构造查询数据 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孙xxx"; break; case 4: name = "钱xxx"; break; default: name = "赵xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion //参数越靠前,优先级越高 //先按score排序,当分数相同时再按grade排序...依次类推 var query = from s in listStudents orderby s.score, s.grade, s.age, s.name select s; foreach (Student st in query) { Console.WriteLine("***************"); Console.WriteLine("姓名:" + st.name); Console.WriteLine("班级:" + st.grade); Console.WriteLine("年龄:" + st.age); Console.WriteLine("分数:" + st.score); } Console.ReadKey(); }
分组
语句:
//按国家分组,并选出大于2的组,形成新的集合 var query = from r in listChampion group r by r.country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new { country = g.Key, count = g.Count() };
例子:
/// <summary> /// 分组 /// </summary> static void Linq6() { List<Champions> listChampion = new List<Champions>(); listChampion.Add(new Champions() { name = "张**", country = "中国" }); listChampion.Add(new Champions() { name = "赵**", country = "中国" }); listChampion.Add(new Champions() { name = "李**", country = "中国" }); listChampion.Add(new Champions() { name = "李**", country = "中国" }); listChampion.Add(new Champions() { name = "Peter", country = "美国" }); listChampion.Add(new Champions() { name = "Hune", country = "美国" }); listChampion.Add(new Champions() { name = "Hune", country = "美国" }); listChampion.Add(new Champions() { name = "Jack", country = "俄罗斯" }); listChampion.Add(new Champions() { name = "Jack", country = "俄罗斯" }); listChampion.Add(new Champions() { name = "Jimi", country = "英国" }); //按国家分组,并选出大于2的组,形成新的集合 var query = from r in listChampion group r by r.country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new { country = g.Key, count = g.Count() }; foreach (var o in query) { Console.WriteLine("国家:{0},冠军数:{1}个", o.country, o.count); } Console.ReadKey(); }
联合查询-join
语句:
//查询出集合qSt中year等于集合qSc中year的元素并形成新的集合 var qjoin = from r in qSt join c in qSc on r.year equals c.year select new { Year = r.year, stName = r.name, scName = c.name };
例子:
/// <summary> /// 联合查询-join /// </summary> static void Linq7() { List<s> pSt = new List<s>(); pSt.Add(new s() {year=1999,name="xxx" }); pSt.Add(new s() { year = 2000, name = "xxx" }); pSt.Add(new s() { year = 2001, name = "xxx" }); pSt.Add(new s() { year = 2010, name = "xxx" }); List<school> pSc = new List<school>(); pSc.Add(new school() { year = 1999, name = "***" }); pSc.Add(new school() { year = 2001, name = "***" }); pSc.Add(new school() { year = 2002, name = "***" }); pSc.Add(new school() { year = 2010, name = "***" }); pSc.Add(new school() { year = 2012, name = "***" }); var qSt = from r in pSt where r.year >= 2000 select r; var qSc = from r in pSc where r.year >= 2000 select r; //查询出集合qSt中year等于集合qSc中year的元素并形成新的集合 var qjoin = from r in qSt join c in qSc on r.year equals c.year select new { Year = r.year, stName = r.name, scName = c.name }; foreach (var ite in qjoin) { Console.WriteLine(ite.Year + " " + ite.scName + " " + ite.stName); Console.WriteLine(""); } Console.ReadKey(); }
合并-zip()
.Net4.0新增,可对两个相关的序列进行合并。
语句:
/*若合并两项项数不同,则在达到较小集合的末尾时停止*/ var qZip = qSc.Zip(qSt, (first, second) =>string.Format("Year:{0},Name:{1}.", first.Year,second.Name));//返回值qZip为字符串集合
例子:
/// <summary> /// 合并-zip()-.Net4.0新增,可对两个相关的序列进行合并 /// </summary> static void Linq8() { List<s> pSt = new List<s>(); pSt.Add(new s() { year = 1999, name = "一xxx" }); pSt.Add(new s() { year = 2000, name = "二xxx" }); pSt.Add(new s() { year = 2001, name = "三xxx" }); pSt.Add(new s() { year = 2010, name = "四xxx" }); pSt.Add(new s() { year = 2010, name = "五xxx" }); List<school> pSc = new List<school>(); pSc.Add(new school() { year = 1999, name = "1***" }); pSc.Add(new school() { year = 2012, name = "2***" }); pSc.Add(new school() { year = 2012, name = "3***" }); pSc.Add(new school() { year = 2012, name = "4***" }); pSc.Add(new school() { year = 2012, name = "5***" }); var qSt = from r in pSt where r.year >= 2000 orderby r.year select new { Year = r.year, Name = r.name }; var qSc = from r in pSc where r.year >= 2000 orderby r.year select new { Year = r.year, Name = r.name }; /*若合并两项项数不同,则在达到较小集合的末尾时停止*/ var qZip = qSc.Zip(qSt, (first, second) =>string.Format("Year:{0},Name:{1}.", first.Year,second.Name));//返回值qZip为字符串集合 foreach (var ite in qZip) { Console.WriteLine(ite); } Console.ReadKey(); }
分区(分页)
通过Take()和Skip()实现只显示部分查询结果。
语句:
//通过skip跳过指定数量的元素,再通过take提取固定长度元素,可实现分页 var qr = (from r in listStudents orderby r.score descending select r).Skip(i * pageSize).Take(5); //var qr2 = listStudents.OrderByDescending(r => r.score).Select(r => r).Skip(i * pageSize).Take(5);//或
例子
/// <summary> /// 分区(分页)-通过Take()和Skip()实现只显示部分查询结果 /// </summary> static void Linq9() { #region 构造查询数据 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孙xxx"; break; case 4: name = "钱xxx"; break; default: name = "赵xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion int pageSize = 5; int numofPage = (int)Math.Ceiling(listStudents.Count /(double)pageSize); for (int i = 0; i < numofPage; i++) { Console.WriteLine("第{0}页", i); //通过skip跳过指定数量的元素,再通过take提取固定长度元素,可实现分页 var qr = (from r in listStudents orderby r.score descending select r).Skip(i * pageSize).Take(5); //var qr2 = listStudents.OrderByDescending(r => r.score).Select(r => r).Skip(i * pageSize).Take(5);//或 foreach (var ite in qr) { Console.WriteLine(ite.name); Console.WriteLine(ite.score); } Console.WriteLine(""); } Console.ReadKey(); }
并行linq
并行查询可以分解查询的工作,使其分布在多个线程上。当pc拥有多个cpu时,可以看到并行查询带来的改进效果。并行LINQ适用于大型的集合查询,并拥有一定的优势。使用
System.Collections.Concurrent.Partitioner.Create
可以手动创建分区器。
语法:
var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//并行查询 //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查询(Lambda表达式)
例子:
/// <summary> /// 并行linq /// </summary> static void Linq11() { Console.WriteLine("开始构造大数组..."); //构造大数组 const int count = 100000000; var data = new int[count]; var r = new Random(); for (int i = 0; i < count; i++) { data[i] = r.Next(40); } Console.WriteLine("开始计算..."); var st = System.DateTime.Now; var sum = (from x in data where x > 20 select x).Sum();//常规linq-耗时1.8641s var st2 = System.DateTime.Now; var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//并行查询-耗时0.6620s //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查询----x3 => x3 > 20(Lambda表达式) var st3 = System.DateTime.Now; /*Partitioner.Create 手动创建分区器 * Create具有多个重载,可依据需求进行分区 */ var sum4 = (from c in System.Collections.Concurrent.Partitioner.Create(data, true).AsParallel() where c > 20 select c).Sum(); var dt1 = st2 - st; var dt2 = st3 - st2; Console.WriteLine("常规linq耗时:{0}s",dt1.TotalSeconds.ToString()); Console.WriteLine("并行linq耗时:{0}s", dt2.TotalSeconds.ToString()); Console.ReadKey(); }
输出结果:
可以粗鲁的认为并行linq对于大集合的查询是优势比较明显的。
取消长时间运行的并行linq查询
对于并行ling而言,可以设置可以利用System.Threading.CancellationTokenSource设置取消操作。
语法:
//通过.WithCancellation(cts.Token)设置 var sum = (from x in data.AsParallel().WithCancellation(cts.Token) where x < 20 select x).Average();
例子:
/// <summary> /// 取消长时间运行的并行linq查询 /// </summary> static void Linq12() { //构造大数组 const int count = 100000000; var data = new int[count]; var r = new Random(); for (int i = 0; i < count; i++) { data[i] = r.Next(40); } var cts = new System.Threading.CancellationTokenSource(); new System.Threading.Thread(() => { try { //通过.WithCancellation(cts.Token)设置 var sum = (from x in data.AsParallel().WithCancellation(cts.Token) where x < 20 select x).Average(); Console.WriteLine("sum:{0}", sum); } catch(OperationCanceledException ex) { Console.WriteLine(ex.Message); } }).Start(); Console.WriteLine("计算开始..."); Console.WriteLine("取消请按n!"); var rk = Console.Read(); if(rk=='n'||rk=='N') { cts.Cancel(); } }
至此,对于LINQ已经有了一个基本的了解。
以上就是c# Linq查询详解的详细内容,更多关于c# Linq查询的资料请关注猪先飞其它相关文章!
相关文章
- 我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
- 这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
- 本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
- 这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
- 这篇文章主要介绍了Mybatis Plus select 实现只查询部分字段的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-01
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)
这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
- 这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
- 最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25