-
2022-03-17 15:42:36
语言集成查询 (LINQ) 是一系列直接将查询功能集成到 C# 语言的技术统称。借助 LINQ,查询成为了最高级的语言构造,就像类、方法和事件一样。LINQ 系列技术提供了针对对象 (LINQ to Objects)、关系数据库 (LINQ to SQL) 和 XML (LINQ to XML) 的一致查询体验。
Linq查询语法:
1、扩展方法语法:扩展方法+lambda表达式
2、声明式查询语法:类型SQL查询方式
扩展方法语法(传输链):IEnumerabl<T> query=源集合.Where(过滤,必须bool表达式).OrderBy(排序条件).Select(选择条件)
查询表达式:
var 结果集 = from n in 数据源 where 过滤表达式 orderby 排序 select 投影(选择)
查询表达式需以select或者group结束!
lambda表达式是对匿名方法的简化,任何匿名方法使用的场合lambda表达式都可以替代,并且代码更加简洁。lambda表达式会广泛用于LINQ中。lambda表达式的形式如下:
*①无参的:()=>{处理语句};
②一个参数的:参数=>{处理语句};
③多个参数的:(参数1,参数2,…参数n)=>{处理语句}。
备注:一条处理语句,{}可以省略!关键字:
from...in...:指定要查找的数据以及范围变量,多个from子句则表示从多个数据源查找数据。注意:C#编译器会把"复合from子句"的查询表达式转换为SelectMany()扩展方法
join...in...on...equals...:指定多个数据源的关联方式
let:引入用于存储查询表达式中子表达式结果的范围变量,通常能达到层次感会更好,使代码更易于月的
orderby、descending:指定元素的排序字段和排序方式,当有多个排序字段时,由字段顺序确定主次关系,可指定升序和降序两种排序方式
where:指定元素的筛选条件,多个where子句则表示了并列条件,必须全部都满足才能入选,每个where子句可以使用&&、||连接多个条件表达式
group:指定元素的分组字段
select:指定查询要返回的目标数据,可以指定任何类型,甚至是匿名类型(目前通常被指定为匿名类型)
into:提供一个临时的标识符,该标识符可以引用join、group和select子句的结果。(1)直接出现在join子句之后的into关键字会被翻译为GroupJoin。(2)select或group子句字后的into它会重新开始一个查询,让我们可以继续引入where、orderby和select子句,它是对分步构建查询表达式的一种简写方式。Linq语句:
1.筛选
var res=resources.Where(r=>r.id==2&&r.name.Contains("小"));//扩展方法语法 var res=from r in resources where r.id==2&&r.name.Contains("小") select r;//查询表达式
2.用索引筛选
/*在Where()方法的重载中,可以传递第 二个参数----索引。索引是筛选器返回的每个结果的计数器可以在表达式中使用这个索引,执行 基于索引的计算. */ var res= resources.Where((r, index) => r.Name.StartsWith("小") && index % 2 != 0);
3.用类型筛选
/*在Where()方法的重载中,可以传递第 OfTypeO扩展方法把 string类传送给泛型参数,就从集合中仅返回字符串 */ object[] data = { "one", 2, 3, "four", "five", 6 }; var query = data.OfType<string>();
4.复合的from子句
var res=from r in resources from s in students where r.id==s.id orderby r.name select r.id +r.name
5.排序
var res=from r in resources where r.id==2&&r.name.Contains("小") OrderByDescending(r => r.name) select r; var res=from r in resources where r.id==2&&r.name.Contains("小") orderby r.name descending select r;
6.分组
var res=from r in resources where r.id==2&&r.name.Contains("小") orderby r.id descending, r.name select { ID=r.id, Name=r.name };
7.对嵌套的对象分组
var res = from r in resources join s in students on r.name equals s.name into groups //分组 orderby groups.Count() // 这个可以获得数量 select new { Name= k, Count = groups.Count() };
8.内连接(且 两个集合中有都有匹配就返回筛选内容)
var res=from r in resources join s in students on r.id==s.id select new { ID=r.id, Name=r.name };
9.外连接(或 左连接:即使右边没有匹配的也返回左边内容,右连接:即使左边没有匹配的也返回右边的内容)
var res=from r in resources left join s in students on r.id==s.id select new { ID=r.id, Name=r.name };
10.组连接
/* 分组联接可用于产生分层数据结构。 它将第一个集合中的每个元素与第二个集合中的一组相关元素进行配对。 */ var res=from r in resources join s in students on r.id==s.id into groups select new { resource=groups, Name=r.name };
11.通过Take()和Skip()实现只显示部分查询结果
var res=(resources.Where(r=>r.id==2&&r.name.Contains("小"))).Take(3);
12.zip可对两个相关的序列进行合并
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为字符串集合
参考:
更多相关内容 -
c# Linq常用的小技巧
2020-12-17 05:39:32在C#语言发展的历史长河中,Linq是一个极其重要的里程碑! Linq的语法吸取了SQL语法的特性,同时配合Lambda表达式又可以使代码更加优雅! 可以这么说,用好了Linq可以大大提高程序猿的工作效率,毕竟我们的日常工作... -
c# linq的差集,并集,交集,去重代码(分享)
2020-08-28 18:27:13下面小编就为大家分享一篇c# linq的差集,并集,交集,去重代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 -
C# linq查询之动态OrderBy用法实例
2020-09-03 14:23:00主要介绍了C# linq查询之动态OrderBy用法,实例分析了C#采用linq方式查询时动态排序的相关技巧,需要的朋友可以参考下 -
LINQ-Async:用于异步任务的C#LINQ异步扩展方法库
2021-05-15 17:45:39什么是LINQ异步? LINQ-Async允许您链接异步任务并使用流畅的API命令异步谓词。 特征 OrderByPredicateCompletion 同时启动Predicate OrderByCompletion 选择结果 下载 PM> Install-Package Z.Linq.Async LINQ... -
C# LinqXML使用LINQ技术创建XML文件
2017-10-27 10:54:55亲测好用,利用c# 的LinqXML技术 使用LINQ技术创建XML文件 -
C# LinqXML查找指定名称的元素
2017-10-27 10:35:07C# LinqXML查找指定名称的元素C# LinqXML查找指定名称的元素 -
C# LinqXML访问指定节点的父节点
2017-10-27 10:47:49利用c# 的LinqXML技术 访问指定节点的父节点的详细信息。 -
C# LinqXML返回节点集合中每个节点的所有
2017-10-27 10:39:12利用c# 的Linq技术 返回节点集合中每个节点的所有节点。 -
C# LINQ的基本使用方法示例
2020-08-18 14:53:45主要给大家介绍了关于C# LINQ的基本使用教程,文中通过示例代码介绍的非常详细,对大家学习或者使用C# LINQ具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧 -
C# LinqXML查找根元素
2017-10-27 10:33:54C# LinqXML查找根元素C# LinqXML查找根元素C# LinqXML查找根元素 -
C# LinqXML返回元素集合中每个元素的所有
2017-10-27 10:45:24利用c# 的Linq技术 返回元素集合中每个元素的所有元素属性。 -
c#Linq distinct不会调用Equals方法详解
2021-01-19 23:25:07我有以下课程 public class ModInfo : IEquatable { public int ID { get; set; } public string MD5 { get; set; } public bool Equals(ModInfo other) ... return other.MD5.Equals(MD5);...public void Relo -
C# LINQ to XML应用介绍
2021-01-20 06:45:28后来 .Net又引入了LINQ,于是LINQ to XML也就应运而生,所以在.Net中,不仅可以用W3C XML DOM标准,还可以使用LINQ to XML来操作XML文档。下面就来简单介绍一下如何使用LINQ to XML。 (一) 加载 加载XML比较常用的... -
C# Linq实战
2018-07-20 14:13:07第1章 LINQ简介 1.1 LINQ是什么 1.2 为什么需要LINQ 1.3 LINQ的设计目标及起源 1.4 LINQ to Objects初步:查询内存中的集合 1.5 LINQ to XML初步:查询XML文档 1.6 LINQ to SQL初步... -
C# Linq查询
2018-09-28 08:46:58Linq相关例子和使用,代码在visual studio2017上编译通过 -
c#使用linq把多列的List转化为只有指定列的List
2021-01-21 17:19:55您可能感兴趣的文章:C#中Linq查询基本操作使用实例c#中LINQ的基本用法实例C#中的Linq to Xml详解C# Linq读取XML文件的实例C#使用linq对数组进行筛选排序的方法C#使用LINQ查询表达式的基本子句总结C#使用linq查询大... -
C# Linq详解
2021-03-30 09:36:56LINQ 查询简介TOC LINQ 通过提供处理各种数据源和数据格式的数据的一致模型,简化了这一情况。 在 LINQ 查询中,始终会用到对象。 可以使用相同的基本编码模式来查询和转换 XML 文档、SQL 数据库、ADO.NET 数据集、...LINQ 查询简介TOC
LINQ 通过提供处理各种数据源和数据格式的数据的一致模型,简化了这一情况。 在 LINQ 查询中,始终会用到对象。 可以使用相同的基本编码模式来查询和转换 XML 文档、SQL 数据库、ADO.NET 数据集、.NET 集合中的数据以及 LINQ 提供程序可用的任何其他格式的数据。
查询操作的三个部分
所有 LINQ 查询操作都由以下三个不同的操作组成:
- 获取数据源
- 创建查询
- 执行查询。
下面的示例演示如何用源代码表示查询操作的三个部分。 为方便起见,此示例将一个整数数组用作数据源;但其中涉及的概念同样适用于其他数据源。 本主题的其余部分也会引用此示例。
class IntroToLINQ { static void Main() { // The Three Parts of a LINQ Query: // 1. Data source. int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // 2. Query creation. // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; // 3. Query execution. foreach (int num in numQuery) { Console.Write("{0,1} ", num); } } }
下图演示完整的查询操作。 在 LINQ 中,查询的执行不同于查询本身。 换句话说,仅通过创建查询变量不会检索到任何数据。
using System; using System.Collections.Generic; using System.Linq; namespace test { class Program { private static List<Customer> customers = new List<Customer>() { new Customer{ City="London",Name="Devon"}, new Customer{ City="London",Name="Steve"} , new Customer{ City="Paris",Name="Jane"} }; static void Main(string[] args) { Console.WriteLine("Hello World!"); } } public class Customer { public string Name { get; set; } public string City { get; set; } } }
基本 LINQ 查询操作
在 LINQ 查询中,第一步是指定数据源。 和大多数编程语言相同,在使用 C# 时也必须先声明变量,然后才能使用它。 在 LINQ 查询中,先使用 from 子句引入数据源 (customers) 和范围变量 (cust)。
//queryAllCustomers is an IEnumerable<Customer> var queryAllCustomers = from cust in customers select cust;
范围变量就像 foreach 循环中的迭代变量,但查询表达式中不会真正发生迭代。 当执行查询时,范围变量将充当对 customers 中每个连续的元素的引用。 由于编译器可以推断 cust 的类型,因此无需显式指定它。 可通过 let 子句引入其他范围变量。
对于非泛型数据源(例如 ArrayList),必须显式键入范围变量。 有关详细信息,请参阅如何使用 LINQ (C#) 和 From 子句查询 ArrayList。筛选 (where )
或许,最常见的查询操作是以布尔表达式的形式应用筛选器。 筛选器使查询仅返回表达式为 true 的元素。 将通过使用 where 子句生成结果。 筛选器实际指定要从源序列排除哪些元素。 在下列示例中,仅返回地址位于“London”的 customers。
var queryLondonCustomers = from cust in customers where cust.City == "London" select cust;
可使用熟悉的 C# 逻辑 AND 和 OR 运算符,在 where 子句中根据需要应用尽可能多的筛选器表达式。 例如,若要仅返回来自“London”的客户 AND 该客户名称为“Devon”,可编写以下代码:
where cust.City == "London" && cust.Name == "Devon"
要返回来自 London 或 Paris 的客户,可编写以下代码:
where cust.City == "London" || cust.City == "Paris"
中间件排序 (orderby)
对返回的数据进行排序通常很方便。 orderby 子句根据要排序类型的默认比较器,对返回序列中的元素排序。 例如,基于 Name 属性,可将下列查询扩展为对结果排序。 由于 Name 是字符串,默认比较器将按字母顺序从 A 到 Z 进行排序
var queryLondonCustomers3 = from cust in customers where cust.City == "London" orderby cust.Name ascending select cust;
要对结果进行从 Z 到 A 的逆序排序,请使用 orderby…descending 子句
分组(group)
group 子句用于对根据您指定的键所获得的结果进行分组。 例如,可指定按 City 对结果进行分组,使来自 London 或 Paris 的所有客户位于单独的组内。 在这种情况下,cust.City 是Key。
// queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>> var queryCustomersByCity = from cust in customers group cust by cust.City; // customerGroup is an IGrouping<string, Customer> foreach (var customerGroup in queryCustomersByCity) { Console.WriteLine(customerGroup.Key); foreach (Customer customer in customerGroup) { Console.WriteLine(" {0}", customer.Name); } }
联接(join)
联接操作在不同序列间创建关联,这些序列在数据源中未被显式模块化。 例如,可通过执行联接来查找所有位置相同的客户和分销商。 在 LINQ 中,join 子句始终作用于对象集合,而非直接作用于数据库表。
var innerJoinQuery = from cust in customers join dist in distributors on cust.City equals dist.City select new { CustomerName = cust.Name, DistributorName = dist.Name };
选择(select)
select 子句生成查询结果并指定每个返回的元素的“形状”或类型。 例如,可以指定结果包含的是整个 Customer 对象、仅一个成员、成员的子集,还是某个基于计算或新对象创建的完全不同的结果类型。 当 select 子句生成除源元素副本以外的内容时,该操作称为投影。 使用投影转换数据是 LINQ 查询表达式的一种强大功能
标准查询运算符概述
标准查询运算符是组成 LINQ 模式的方法。 这些方法中的大多数都作用于序列;其中序列指其类型实现 IEnumerable 接口或 IQueryable 接口的对象。 标准查询运算符提供包括筛选、投影、聚合、排序等在内的查询功能。
共有两组 LINQ 标准查询运算符,一组作用于类型 IEnumerable 的对象,另一组作用于类型 IQueryable 的对象。 构成每个集合的方法分别是 Enumerable 和 Queryable 类的静态成员。 这些方法被定义为作为方法运行目标的类型的扩展方法。 可以使用静态方法语法或实例方法语法来调用扩展方法。
此外,多个标准查询运算符方法作用于那些基于 IEnumerable 或 IQueryable 的类型外的类型。 Enumerable 类型定义了两种这样的方法,这两种方法都作用于类型 IEnumerable 的对象。 这些方法(Cast(IEnumerable) 和 OfType(IEnumerable))均允许在 LINQ 模式中查询非参数化或非泛型集合。 这些方法通过创建一个强类型的对象集合来实现这一点。 Queryable 类定义了两种类似的方法 Cast(IQueryable) 和 OfType(IQueryable),这两种方法都作用于类型 Queryable 的对象。
各个标准查询运算符在执行时间上有所不同,具体情况取决于它们是返回单一值还是值序列。 返回单一实例值的这些方法(例如 Average 和 Sum)立即执行。 返回序列的方法会延迟查询执行,并返回一个可枚举的对象。
对于在内存中集合上运行的方法(即扩展 IEnumerable 的那些方法),返回的可枚举对象将捕获传递到方法的参数。 在枚举该对象时,将使用查询运算符的逻辑,并返回查询结果。
相反,扩展 IQueryable 的方法不会实现任何查询行为。 它们生成一个表示要执行的查询的表达式树。 源 IQueryable 对象执行查询处理。
可以在一个查询中将对查询方法的调用链接在一起,这就使得查询的复杂性可能会变得不确定。
下面的代码示例演示如何使用标准查询运算符来获取有关序列的信息。string sentence = "the quick brown fox jumps over the lazy dog"; // Split the string into individual words to create a collection. string[] words = sentence.Split(' '); // Using query expression syntax. var query = from word in words group word.ToUpper() by word.Length into gr orderby gr.Key select new { Length = gr.Key, Words = gr }; // Using method-based query syntax. var query2 = words. GroupBy(w => w.Length, w => w.ToUpper()). Select(g => new { Length = g.Key, Words = g }). OrderBy(o => o.Length); foreach (var obj in query) { Console.WriteLine("Words of length {0}:", obj.Length); foreach (string word in obj.Words) Console.WriteLine(word); } // This code example produces the following output: // // Words of length 3: // THE // FOX // THE // DOG // Words of length 4: // OVER // LAZY // Words of length 5: // QUICK // BROWN // JUMPS
查询表达式语法表
下表列出包含等效查询表达式子句的标准查询运算符。
方法 C# 查询表达式语法 Cast 使用显式类型化范围变量,例如:from int i in numbers GroupBy group … by 或 group … by … into GroupJoin join … in … on … equals … into … Join join … in … on … equals … OrderBy orderby OrderByDescending orderby … descending Select select SelectMany 多个 from 子句。 ThenBy orderby …, … ThenByDescending orderby …, … descending Where where 对数据排序
方法
方法名 描述 C# 查询表达式语法 OrderBy 按升序对值排序。 orderby OrderByDescending 按降序对值排序 orderby … descending ThenBy 按升序执行次要排序 orderby …, … ThenByDescending 按降序执行次要排序。 orderby …, … descending Reverse 反转集合中元素的顺序。 不适用。 主要升序排序
下面的示例演示如何在 LINQ 查询中使用 orderby 子句按字符串长度对数组中的字符串进行升序排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Length select word; foreach (string str in query) Console.WriteLine(str); /* This code produces the following output: the fox quick brown jumps */
主要降序排序
下面的示例演示如何在 LINQ 查询中使用 orderby descending 子句按字符串的第一个字母对字符串进行降序排序
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Substring(0, 1) descending select word; foreach (string str in query) Console.WriteLine(str); /* This code produces the following output: the quick jumps fox brown */
次要升序排序
下面的示例演示如何在 LINQ 查询中使用 orderby 子句对数组中的字符串执行主要和次要排序。 首先按字符串长度,其次按字符串的第一个字母,对字符串进行升序排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Length, word.Substring(0, 1) select word; foreach (string str in query) Console.WriteLine(str); /* This code produces the following output: fox the brown jumps quick */
次要降序排序
下面的示例演示如何在 LINQ 查询中使用 orderby descending 子句按升序执行主要排序,按降序执行次要排序。 首先按字符串长度,其次按字符串的第一个字母,对字符串进行排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Length, word.Substring(0, 1) descending select word; foreach (string str in query) Console.WriteLine(str); /* This code produces the following output: the fox quick jumps brown */
Set 运算
LINQ 中的集运算是指根据相同或不同集合(或集)中是否存在等效元素来生成结果集的查询运算。
下节列出了执行集运算的标准查询运算符方法。方法名 描述 Distinct 删除集合中的重复值。 Except 返回差集,差集指位于一个集合但不位于另一个集合的元素。 Intersect 返回交集,交集指同时出现在两个集合中的元素 。 Union 返回并集,并集指位于两个集合中任一集合的唯一的元素。 Distinct
以下示例演示字符序列上 Enumerable.Distinct 方法的行为。 返回的序列包含输入序列的唯一元素。
string[] planets = { "Mercury", "Venus", "Venus", "Earth", "Mars", "Earth" }; IEnumerable<string> query = from planet in planets.Distinct() select planet; foreach (var str in query) { Console.WriteLine(str); } /* This code produces the following output: * * Mercury * Venus * Earth * Mars */
Except
以下示例演示 Enumerable.Except 的行为。 返回的序列只包含位于第一个输入序列但不位于第二个输入序列的元素
string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" }; string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" }; IEnumerable<string> query = from planet in planets1.Except(planets2) select planet; foreach (var str in query) { Console.WriteLine(str); } /* This code produces the following output: * * Venus */
Intersect
以下示例演示 Enumerable.Intersect 的行为。 返回的序列包含两个输入序列共有的元素。
string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" }; string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" }; IEnumerable<string> query = from planet in planets1.Intersect(planets2) select planet; foreach (var str in query) { Console.WriteLine(str); } /* This code produces the following output: * * Mercury * Earth * Jupiter */
Union
以下示例演示对两个字符序列执行的联合操作。 返回的序列包含两个输入序列的唯一元素
string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" }; string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" }; IEnumerable<string> query = from planet in planets1.Union(planets2) select planet; foreach (var str in query) { Console.WriteLine(str); } /* This code produces the following output: * * Mercury * Venus * Earth * Jupiter * Mars */
筛选数据 (Where/OfType)
筛选是指将结果集限制为仅包含满足指定条件的元素的操作。 它也称为选定内容。
下图演示了对字符序列进行筛选的结果。 筛选操作的谓词指定字符必须为“A”。
方法名 描述 C# 查询表达式语法 OfType 根据其转换为特定类型的能力选择值 不适用。 Where 选择基于谓词函数的值。 where 示例
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words where word.Length == 3 select word; foreach (string str in query) Console.WriteLine(str); /* This code produces the following output: the fox */
限定符运算
限定符运算返回一个 Boolean 值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件。
下图描述了两个不同源序列上的两个不同限定符运算。 第一个运算询问是否有一个或多个元素为字符“A”,结果为 true。 第二个运算询问是否所有元素都为字符“A”,结果为 true。
方法名 描述 C# 查询表达式语法 All 确定是否序列中的所有元素都满足条件 不适用。 Any 确定序列中是否有元素满足条件。 不适用。 Contains 确定序列是否包含指定的元素。 不适用。 All
以下示例使用 All 检查所有字符串是否为特定长度。
class Market { public string Name { get; set; } public string[] Items { get; set; } } public static void Example() { List<Market> markets = new List<Market> { new Market { Name = "Emily's", Items = new string[] { "kiwi", "cheery", "banana" } }, new Market { Name = "Kim's", Items = new string[] { "melon", "mango", "olive" } }, new Market { Name = "Adam's", Items = new string[] { "kiwi", "apple", "orange" } }, }; // Determine which market have all fruit names length equal to 5 IEnumerable<string> names = from market in markets where market.Items.All(item => item.Length == 5) select market.Name; foreach (string name in names) { Console.WriteLine($"{name} market"); } // This code produces the following output: // // Kim's market }
Any
以下示例使用 Any 检查所有字符串是否以“o”开头。
class Market { public string Name { get; set; } public string[] Items { get; set; } } public static void Example() { List<Market> markets = new List<Market> { new Market { Name = "Emily's", Items = new string[] { "kiwi", "cheery", "banana" } }, new Market { Name = "Kim's", Items = new string[] { "melon", "mango", "olive" } }, new Market { Name = "Adam's", Items = new string[] { "kiwi", "apple", "orange" } }, }; // Determine which market have any fruit names start with 'o' IEnumerable<string> names = from market in markets where market.Items.Any(item => item.StartsWith("o")) select market.Name; foreach (string name in names) { Console.WriteLine($"{name} market"); } // This code produces the following output: // // Kim's market // Adam's market }
Contains
以下示例使用 Contains 检查所有数组是否具有特定元素。
class Market { public string Name { get; set; } public string[] Items { get; set; } } public static void Example() { List<Market> markets = new List<Market> { new Market { Name = "Emily's", Items = new string[] { "kiwi", "cheery", "banana" } }, new Market { Name = "Kim's", Items = new string[] { "melon", "mango", "olive" } }, new Market { Name = "Adam's", Items = new string[] { "kiwi", "apple", "orange" } }, }; // Determine which market contains fruit names equal 'kiwi' IEnumerable<string> names = from market in markets where market.Items.Contains("kiwi") select market.Name; foreach (string name in names) { Console.WriteLine($"{name} market"); } // This code produces the following output: // // Emily's market // Adam's market }
投影运算
投影是指将对象转换为一种新形式的操作,该形式通常只包含那些将随后使用的属性。 通过使用投影,您可以构造从每个对象生成的新类型。 可以投影属性,并对该属性执行数学函数。 还可以在不更改原始对象的情况下投影该对象。
方法名 描述 C# 查询表达式语法 Select 投影基于转换函数的值。 select。 SelectMany 投影基于转换函数的值序列,然后将它们展平为一个序列 使用多个 from 子句 Select
下面的示例使用 select 子句来投影字符串列表中每个字符串的第一个字母。
List<string> words = new List<string>() { "an", "apple", "a", "day" }; var query = from word in words select word.Substring(0, 1); foreach (string s in query) Console.WriteLine(s); /* This code produces the following output: a a a d */
SelectMany
下面的示例使用多个 from 子句来投影字符串列表中每个字符串中的每个单词。
List<string> phrases = new List<string>() { "an apple a day", "the quick brown fox" }; var query = from phrase in phrases from word in phrase.Split(' ') select word; foreach (string s in query) Console.WriteLine(s); /* This code produces the following output: an apple a day the quick brown fox */
Select() 和 SelectMany()比较
下面的示例比较 Select() 和 SelectMany() 的行为。 代码通过从源集合的每个花卉名称列表中提取前两项来创建一个“Flowers”。 此示例中,transform 函数 Select<TSource,TResult>(IEnumerable, Func<TSource,TResult>) 使用的“单值”本身即是值的集合。 这需要额外的 foreach 循环,以便枚举每个子序列中的每个字符串。
class Bouquet { public List<string> Flowers { get; set; } } static void SelectVsSelectMany() { List<Bouquet> bouquets = new List<Bouquet>() { new Bouquet { Flowers = new List<string> { "sunflower", "daisy", "daffodil", "larkspur" }}, new Bouquet{ Flowers = new List<string> { "tulip", "rose", "orchid" }}, new Bouquet{ Flowers = new List<string> { "gladiolis", "lily", "snapdragon", "aster", "protea" }}, new Bouquet{ Flowers = new List<string> { "larkspur", "lilac", "iris", "dahlia" }} }; // *********** Select *********** IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers); // ********* SelectMany ********* IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers); Console.WriteLine("Results by using Select():"); // Note the extra foreach loop here. foreach (IEnumerable<String> collection in query1) foreach (string item in collection) Console.WriteLine(item); Console.WriteLine("\nResults by using SelectMany():"); foreach (string item in query2) Console.WriteLine(item); /* This code produces the following output: Results by using Select(): sunflower daisy daffodil larkspur tulip rose orchid gladiolis lily snapdragon aster protea larkspur lilac iris dahlia Results by using SelectMany(): sunflower daisy daffodil larkspur tulip rose orchid gladiolis lily snapdragon aster protea larkspur lilac iris dahlia */ }
数据分区
LINQ 中的分区是指将输入序列划分为两个部分的操作,无需重新排列元素,然后返回其中一个部分。
下图显示对字符序列进行三种不同的分区操作的结果。 第一个操作返回序列中的前三个元素。 第二个操作跳过前三个元素,返回剩余元素。 第三个操作跳过序列中的前两个元素,返回接下来的三个元素。
运算符名称 描述 C# 查询表达式语法 Skip 跳过序列中指定位置之前的元素。 不适用。 SkipWhile 基于谓词函数跳过元素,直到元素不符合条件。 不适用 Take 获取序列中指定位置之前的元素。 不适用。 TakeWhile 基于谓词函数获取元素,直到元素不符合条件。 不适用。 Join 操作
联接两个数据源就是将一个数据源中的对象与另一个数据源中具有相同公共属性的对象相关联。
当查询所面向的数据源相互之间具有无法直接领会的关系时,Join 就成为一项重要的运算。 在面向对象的编程中,这可能意味着在未建模对象之间进行关联,例如对单向关系进行反向推理。 下面是单向关系的一个示例:Customer 类有一个类型为 City 的属性,但 City 类没有作为 Customer 对象集合的属性。 如果你具有一个 City 对象列表,并且要查找每个城市中的所有客户,则可以使用联接运算完成此项查找。
LINQ 框架中提供的 join 方法包括 Join 和 GroupJoin。 这些方法执行同等联接,即根据 2 个数据源的键是否相等来匹配这 2 个数据源的联接。 (与此相较,Transact-SQL 支持除“等于”之外的联接运算符,例如“小于”运算符。)用关系数据库术语表达,就是说 Join 实现了内部联接,这种联接只返回那些在另一个数据集中具有匹配项的对象。 GroupJoin 方法在关系数据库术语中没有直接等效项,但实现了内部联接和左外部联接的超集。 左外部联接是指返回第一个(左侧)数据源的每个元素的联接,即使其他数据源中没有关联元素。
下图显示了一个概念性视图,其中包含两个集合以及这两个集合中的包含在内部联接或左外部联接中的元素.
运算符名称 描述 C# 查询表达式语法 Join 根据键选择器函数 Join 两个序列并提取值对。 join … in … on … equals … GroupJoin 根据键选择器函数 Join 两个序列,并对每个元素的结果匹配项进行分组。 join … in … on … equals … into … Join
下面的示例使用 join … in … on … equals … 子句基于特定值联接两个序列:
class Product { public string Name { get; set; } public int CategoryId { get; set; } } class Category { public int Id { get; set; } public string CategoryName { get; set; } } public static void Example() { List<Product> products = new List<Product> { new Product { Name = "Cola", CategoryId = 0 }, new Product { Name = "Tea", CategoryId = 0 }, new Product { Name = "Apple", CategoryId = 1 }, new Product { Name = "Kiwi", CategoryId = 1 }, new Product { Name = "Carrot", CategoryId = 2 }, }; List<Category> categories = new List<Category> { new Category { Id = 0, CategoryName = "Beverage" }, new Category { Id = 1, CategoryName = "Fruit" }, new Category { Id = 2, CategoryName = "Vegetable" } }; // Join products and categories based on CategoryId var query = from product in products join category in categories on product.CategoryId equals category.Id select new { product.Name, category.CategoryName }; foreach (var item in query) { Console.WriteLine($"{item.Name} - {item.CategoryName}"); } // This code produces the following output: // // Cola - Beverage // Tea - Beverage // Apple - Fruit // Kiwi - Fruit // Carrot - Vegetable }
GroupJoin
下面的示例使用 join … in … on … equals … into … 子句基于特定值联接两个序列,并对每个元素的结果匹配项进行分组
class Product { public string Name { get; set; } public int CategoryId { get; set; } } class Category { public int Id { get; set; } public string CategoryName { get; set; } } public static void Example() { List<Product> products = new List<Product> { new Product { Name = "Cola", CategoryId = 0 }, new Product { Name = "Tea", CategoryId = 0 }, new Product { Name = "Apple", CategoryId = 1 }, new Product { Name = "Kiwi", CategoryId = 1 }, new Product { Name = "Carrot", CategoryId = 2 }, }; List<Category> categories = new List<Category> { new Category { Id = 0, CategoryName = "Beverage" }, new Category { Id = 1, CategoryName = "Fruit" }, new Category { Id = 2, CategoryName = "Vegetable" } }; // Join categories and product based on CategoryId and grouping result var productGroups = from category in categories join product in products on category.Id equals product.CategoryId into productGroup select productGroup; foreach (IEnumerable<Product> productGroup in productGroups) { Console.WriteLine("Group"); foreach (Product product in productGroup) { Console.WriteLine($"{product.Name,8}"); } } // This code produces the following output: // // Group // Cola // Tea // Group // Apple // Kiwi // Group // Carrot }
对数据分组
分组是指将数据分到不同的组,使每组中的元素拥有公共的属性。
下图演示了对字符序列进行分组的结果。 每个组的键是字符。
运算符名称 描述 C# 查询表达式语法 GroupBy 对共享通用属性的元素进行分组。 每组由一个 IGrouping<TKey,TElement> 对象表示。 group … by或group … by … into … ToLookup 将元素插入基于键选择器函数的 Lookup<TKey,TElement>(一种一对多字典)。 不适用 List<int> numbers = new List<int>() { 35, 44, 200, 84, 3987, 4, 199, 329, 446, 208 }; IEnumerable<IGrouping<int, int>> query = from number in numbers group number by number % 2; foreach (var group in query) { Console.WriteLine(group.Key == 0 ? "\nEven numbers:" : "\nOdd numbers:"); foreach (int i in group) Console.WriteLine(i); } /* This code produces the following output: Odd numbers: 35 3987 199 329 Even numbers: 44 200 84 4 446 208 */
Generation Operations
Generation 是指创建新的值序列。
运算符名称 描述 C# 查询表达式语法 DefaultIfEmpty 用默认值单一实例集合替换空集合。 不适用。 Empty 返回一个空集合。 不适用。 Range 生成包含数字序列的集合。 不适用。 Repeat 生成包含一个重复值的集合。 不适用。 Equality Operations
两个序列,其相应元素相等且具有被视为相等的相同数量的元素。
运算符名称 描述 C# 查询表达式语法 SequenceEqual 通过以成对方式比较元素确定两个序列是否相等。 不适用。 Element Operations (元素运算)
元素运算从序列中返回唯一、特定的元素。
运算符名称 描述 C# 查询表达式语法 ElementAt 返回集合中指定索引处的元素。 不适用。 ElementAtOrDefault 返回集合中指定索引处的元素;如果索引超出范围,则返回默认值。 不适用。 First 返回集合的第一个元素或满足条件的第一个元素。 不适用。 FirstOrDefault 返回集合的第一个元素或满足条件的第一个元素。 如果此类元素不存在,则返回默认值。 不适用。 Last 返回集合的最后一个元素或满足条件的最后一个元素。 不适用 LastOrDefault 返回集合的最后一个元素或满足条件的最后一个元素。 如果此类元素不存在,则返回默认值。 不适用。 Single 返回集合的唯一一个元素或满足条件的唯一一个元素。 如果没有要返回的元素或要返回多个元素,则引发 InvalidOperationException。 不适用。 SingleOrDefault 返回集合的唯一一个元素或满足条件的唯一一个元素。 如果没有要返回的元素,则返回默认值。 如果要返回多个元素,则引发 InvalidOperationException。 不适用 Converting Data Types ( 转换数据类型)
转换方法可更改输入对象的类型。
LINQ 查询中的转换运算可用于各种应用程序。 以下是一些示例:- Enumerable.AsEnumerable 方法可用于隐藏类型的标准查询运算符自定义实现。
//Enumerable.AsEnumerable<TSource>(IEnumerable<TSource>) 方法 //public static System.Collections.Generic.IEnumerable<TSource> AsEnumerable<TSource> (this System.Collections.Generic.IEnumerable<TSource> source); //下面的代码示例演示 AsEnumerable<TSource>(IEnumerable<TSource>) Where 当需要标准查询运算符实现时,如何使用隐藏类型的自定义方法。 // Custom class. class Clump<T> : List<T> { // Custom implementation of Where(). public IEnumerable<T> Where(Func<T, bool> predicate) { Console.WriteLine("In Clump's implementation of Where()."); return Enumerable.Where(this, predicate); } } static void AsEnumerableEx1() { // Create a new Clump<T> object. Clump<string> fruitClump = new Clump<string> { "apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry" }; // First call to Where(): // Call Clump's Where() method with a predicate. IEnumerable<string> query1 = fruitClump.Where(fruit => fruit.Contains("o")); Console.WriteLine("query1 has been created.\n"); // Second call to Where(): // First call AsEnumerable() to hide Clump's Where() method and thereby // force System.Linq.Enumerable's Where() method to be called. IEnumerable<string> query2 = fruitClump.AsEnumerable().Where(fruit => fruit.Contains("o")); // Display the output. Console.WriteLine("query2 has been created."); } // This code produces the following output: // // In Clump's implementation of Where(). // query1 has been created. // // query2 has been created.
- Enumerable.OfType 方法可用于为 LINQ 查询启用非参数化集合。
//根据指定类型筛选 IEnumerable 的元素。 //public static System.Collections.Generic.IEnumerable<TResult> OfType<TResult> (this System.Collections.IEnumerable source); System.Collections.ArrayList fruits = new System.Collections.ArrayList(4); fruits.Add("Mango"); fruits.Add("Orange"); fruits.Add("Apple"); fruits.Add(3.0); fruits.Add("Banana"); // Apply OfType() to the ArrayList. IEnumerable<string> query1 = fruits.OfType<string>(); Console.WriteLine("Elements of type 'string' are:"); foreach (string fruit in query1) { Console.WriteLine(fruit); } // The following query shows that the standard query operators such as // Where() can be applied to the ArrayList type after calling OfType(). IEnumerable<string> query2 = fruits.OfType<string>().Where(fruit => fruit.ToLower().Contains("n")); Console.WriteLine("\nThe following strings contain 'n':"); foreach (string fruit in query2) { Console.WriteLine(fruit); } // This code produces the following output: // // Elements of type 'string' are: // Mango // Orange // Apple // Banana // // The following strings contain 'n': // Mango // Orange // Banana
3.Enumerable.ToArray、Enumerable.ToDictionary、Enumerable.ToList 和 Enumerable.ToLookup 方法可用于强制执行即时的查询,而不是将其推迟到枚举该查询时。
//从 IEnumerable<T> 中创建数组。 //public static TSource[] ToArray<TSource> (this System.Collections.Generic.IEnumerable<TSource> source); class Package { public string Company { get; set; } public double Weight { get; set; } } public static void ToArrayEx1() { List<Package> packages = new List<Package> { new Package { Company = "Coho Vineyard", Weight = 25.2 }, new Package { Company = "Lucerne Publishing", Weight = 18.7 }, new Package { Company = "Wingtip Toys", Weight = 6.0 }, new Package { Company = "Adventure Works", Weight = 33.8 } }; string[] companies = packages.Select(pkg => pkg.Company).ToArray(); foreach (string company in companies) { Console.WriteLine(company); } } /* This code produces the following output: Coho Vineyard Lucerne Publishing Wingtip Toys Adventure Works */
Enumerable.ToDictionary 方法
方法名 描述 C# 查询表达式语法 AsEnumerable 返回类型化为 IEnumerable 的输入。 不适用。 AsQueryable 将(泛型)IEnumerable 转换为(泛型)IQueryable。 不适用。 Cast 将集合中的元素转换为指定类型。 使用显式类型化的范围变量。 例如:from string str in words OfType 根据其转换为指定类型的能力筛选值。 不适用。 ToArray 将集合转换为数组。 此方法强制执行查询。 不适用。 ToDictionary 根据键选择器函数将元素放入 Dictionary<TKey,TValue>。 此方法强制执行查询。 不适用。 ToList 将集合转换为 List。 此方法强制执行查询。 不适用。 ToLookup 根据键选择器函数将元素放入 Lookup<TKey,TElement>(一对多字典)。 此方法强制执行查询。 不适用。 示例
下面的代码示例使用显式类型化的范围变量将类型转换为子类型,然后才访问仅在此子类型上可用的成员。
class Plant { public string Name { get; set; } } class CarnivorousPlant : Plant { public string TrapType { get; set; } } static void Cast() { Plant[] plants = new Plant[] { new CarnivorousPlant { Name = "Venus Fly Trap", TrapType = "Snap Trap" }, new CarnivorousPlant { Name = "Pitcher Plant", TrapType = "Pitfall Trap" }, new CarnivorousPlant { Name = "Sundew", TrapType = "Flypaper Trap" }, new CarnivorousPlant { Name = "Waterwheel Plant", TrapType = "Snap Trap" } }; var query = from CarnivorousPlant cPlant in plants where cPlant.TrapType == "Snap Trap" select cPlant; foreach (Plant plant in query) Console.WriteLine(plant.Name); /* This code produces the following output: Venus Fly Trap Waterwheel Plant */ }
Concat Operations (串联运算)
串联是指将一个序列附加到另一个序列的操作。
下图描绘了两个字符序列的串联操作。
方法名 描述 C# 查询表达式语法 Concat 连接两个序列以组成一个序列。 不适用。 Aggregation Operations(集合运算)
聚合运算从值的集合中计算出单个值。 例如,从一个月累计的每日温度值计算出日平均温度值就是一个聚合运算。
下图显示对数字序列进行两种不同聚合操作所得结果。 第一个操作累加数字。 第二个操作返回序列中的最大值。
方法名 描述 C# 查询表达式语法 Aggregate 不适用。 Average 不适用。 Count 不适用。 LongCount 不适用。 Max 不适用。 Min 不适用。 Sum 不适用。 -
C# LinqXML遍历指定节点下的所有对象
2017-10-27 10:32:22C# LinqXML遍历指定节点下的所有对象C# LinqXML遍历指定节点下的所有对象 -
C# LinqXML使用LINQ技术对XML文件进行读取
2017-10-27 10:56:02亲测好用,利用c# 的LinqXML技术 使用LINQ技术对XML文件进行读取 -
C#Linq操作常用方法语句汇总
2022-05-05 15:40:13linq、C#、DataTable linq语句的常用集合1、从DataTable或者list等对象中获取一组时间序列的气温及出现时间
//通过设置降序,然后取第一行 var query= from n in dtResult.AsEnumerable() where n.Field<decimal?>("气温").ToString().Length > 0 && n.Field<decimal?>("气温") != 999999 group n by n.Field<string>("站号") into g select g.OrderByDescending(x => x.Field<decimal?>("气温")).FirstOrDefault();
2、将query1、query2两个结果,通过连接字段合并
var query = from a in query1 join b in query2 on a.Field<string>("站号") equals b.Field<string>("站号") select new { 站号 = a.Field<string>("站号"), 站名 = a.Field<string>("站名"), 气温 = a.Field<decimal?>("气温"), 最高气温出现时间 = a.Field<string>("气温出现时间").PadLeft(4, '0'), };
3、将query结果放到DataTable对象中
query.ToList().ForEach(p => dt.Rows.Add(p.Value1, p.Value2,p.Value3,p.Value4....));
-
.Net C# Linq Where 方法
2021-12-20 13:20:22.Net C# Linq Where 方法Where方法用来做条件筛选,从集合、数组等对象中获取满足条件的元素
参考代码:
1.Lambda获取集合中大于4的数字:
var Number = data.ListInt.Where(n => n > 4); Console.WriteLine(string.Join(' ', Number));
2.Linq语法获取集合中大于4的数字:
var Number1 = from d in data.ListInt where d > 4 select d; Console.WriteLine(string.Join(' ', Number1));
以上两种写法是等价的。
3.Where方法还有一个使用2个参数的重载方法
演示Where方法两个参数的重载,第一个参数为元素,第二个为元素的索引(计算元素大于元素乘元素的索引),第二个参数为元素在集合中的索引
var Number2 = data.ListInt.Where((n, m) => n > n * m); Console.WriteLine(string.Join(' ', Number2));
下面再演示下查询字符型集合
1.查询字符串长度大于2的
var listStr = data.ListStr.Where(s => s.Length > 2); Console.WriteLine(string.Join(' ', listStr));
2.使用Linq语法查询
var listStr1 = from s in data.ListStr where s.Length > 2 && s.IndexOf("q") > -1 select s; Console.WriteLine(string.Join(' ', listStr1));
3.演示重载方法(第二个参数为元素索引)
var listStr2 = data.ListStr.Where((s, i) => s.Length > 2 && i > 4); Console.WriteLine(string.Join(' ', listStr2));
输出结果如下:
集合元素代码:
public class DataList { public List<string> ListStr; public List<int> ListInt; public DataList() { ListStr = new List<string>() { "abc" ,"def","ghi","jkl","mno","pqr","stu","vwx","yz" }; ListInt = new List<int>() { 1,2,3,4,5,6,7,8,9,10 }; } }
-
C# Linq 学会使用,学会自己编写Linq
2021-12-07 14:25:25Linq我暂时理解为,一种内置的非常方便的数据查询的工具 使用 我们先学习它的使用 //数据类 public class DataTest { /// <summary> /// 编号 /// </summary> public int id; /// <... -
.Net C# Linq Select 方法
2021-12-28 18:02:01.Net C# Linq Select 方法 -
C#Linq中的GroupBy应用
2022-02-22 15:12:36// // 返回结果: // IEnumerable> 在 C# 或 IEnumerable(Of IGrouping(Of TKey, // TSource)) 中 Visual Basic 其中每个 System.Linq.IGrouping`2 对象包含一系列对象和一个密钥。 public static IEnumerable> ... -
C# linq经典语法
2016-07-07 16:59:19C# silverlight版本linq语法的经典使用方法 -
C# linq left join
2021-08-06 17:00:47linq双表,多表连接查询 var list = from x in db.lefttable join y in db.righttable on x.id equals y.id into temp from tt in temp.DefaultIfEmpty() select new res {name=x.name,value=