语言集成查询 (LINQ) (C#) | Microsoft 官方文档
LINQ总共包括五个部分:
| 程序集 | 命名空间 | 描述 |
---|---|---|---|
LINQ to Objects | System.Core.dll | System.Linq | 提供对内存中集合操作的支持 |
LINQ to XML | System.Xml.Linq.dll | System.Xml.Linq | 提供对XML数据源的操作的支持 |
LINQ to SQL | System.Data.Linq.dll | System.Data.Linq | 提供对Sql Server数据源操作的支持。(微软已宣布不再更新,推荐使用LINQ to Entities) |
LINQ to DataSet | System.Data.DataSetExtensions.dll | System.Data | 提供对离线数据集DataTable操作的支持。 |
LINQ to Entities | System.Core.dll 和System.Data.Entity.dll | System.Linq和System.Data.Objects | LINQ to Entities 是 Entity Framework 的一部分并且取代LINQ to SQL 作为在数据库上使用 LINQ 的标准机制。 |
目前,除了以下的,还可以下载其他第三方提供程序,例如LINQ to JSON、LINQ to MySQL、LINQ to Amazon、LINQ to Flickr和LINQ to SharePoint。无论使用什么数据源,都可以通过LINQ使用相同的API进行操作。
LINQ查询表达式以from子句开头,以select子句或group子句结束。
在两个子句之间,可以使用where、orderby、join、let等查询操作符。
关键字有: from 、where 、select 、group 、into 、orderby、join、let、in、on、equals、by、ascending、descending等。
编译器会在程序编译时转换LINQ查询,以调用相应的扩展方法。
下面是一个简单的示例,查询一个int数组中小于5的元素,并按照从小到大的顺序排列:
int[] arr = new int[] { 1, 4, 2, 6, 7, 9, 5, 1, 2, 4 }; var query = from r in arr where r < 5 orderby r select r; foreach (var item in query) { Console.WriteLine(item); } Console.ReadLine();
Linq语句最终被转换为调用IEnumerable<T>的扩展方法,在System.Linq.Enumerable静态类中定义了N多扩展。所以只要继承与IEnumerable的类都支持Linq查询 。
标准查询操作符
Enumberable 类定义的标准查询操作符。
LINQ具有“延迟计算”的特性。
Linq的执行不是在Linq的赋值语句执行,而是在通过foreach遍历访问结果时执行。
var names = new List<string> { "Nino", "Alberto", "Juan", "Mike", "Phil" }; var namesWithJ = (from n in names where n.StartsWith("J") orderby n select n); Console.WriteLine("First iteration"); foreach (string name in namesWithJ) { Console.WriteLine(name); } Console.WriteLine(); names.Add("John"); names.Add("Jim"); names.Add("Jack"); names.Add("Denny"); Console.WriteLine("Second iteration"); foreach (string name in namesWithJ) { Console.WriteLine(name); }
返回的结果是:
两次遍历的结果不一样,说明执行并不是在Linq的定义语句执行,而是在foreach执行。
换成如下,两次执行结果就一样了。
var namesWithJ = (from n in names where n.StartsWith("J") orderby n select n ).ToList();
按字母顺序整理:
Cast,Concat,DefaultIfEmpty,Distinct,Except,GroupBy,GroupJoin,Intersect,Join,OfType,OrderBy,OrderByDescending,Repeat,Reverse,Select,SelectMany,Skip,SkipWhile,Take,TakeWhile,ThenBy,ThenByDescending,Union,Where,Zip
对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。Count、Max、Average 和 First 就属于此类查询。
由于查询本身必须使用 foreach 以便返回结果,因此这些查询在执行时不使用显式 foreach 语句,直接立即执行。
Aggregate,All,Any,Average,Contains,Count,ElementAt,ElementAtOrDefault,Empty,First,FirstOrDefault,Last,LastOrDefault,LongCount,Max,Min,Range,SequenceEqual,Single,SingleOrDefault,Sum,ToArray,ToDictionary,ToList,ToLookup
注意:特殊的AsEnumerable运算符,用于处理LINQ to Entities操作远程数据源,将IQueryable远程数据立即转化为本地的IEnumerable集合。若AsEnumerable接收参数是IEnumerable内存集合则什么都不做。
若要强制立即执行任意查询并缓存其结果,可以调用 ToList<TSource> 或 ToArray<TSource> 方法。
通过调用 ToList 或 ToArray,可以将所有数据缓存在单个集合对象中。
var numQuery2 = (from num in numbers where (num % 2) == 0 select num).ToList(); var numQuery3 = (from num in numbers where (num % 2) == 0 select num).ToArray();
语言集成查询 (LINQ) 不仅可用于检索数据,而且还是一个功能强大的数据转换工具。
通过使用 LINQ 查询,您可以将源序列用作输入,并采用多种方式修改它以创建新的输出序列。您可以通过排序和分组来修改该序列,而不必修改元素本身。
但是,LINQ 查询的最强大的功能是能够创建新类型。这一功能在 select 子句中实现。
例如,可以执行下列任务:
class Student { public string Name { get; set; } public int Age { get; set; } public string City { get; set; } public List<int> Scores { get; set; } } class Teacher { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string City { get; set; } } private static void Main(string[] args) { //创建第一个数据源 var students = new List<Student>() { new Student () { Age = 23, City = "广州", Name = "小C", Scores = new List<int> () { 85, 88, 83, 97 } }, new Student () { Age = 18, City = "广西", Name = "小明", Scores = new List<int> () { 86, 78, 85, 90 } }, new Student () { Age = 33, City = "梦里", Name = "小叁", Scores = new List<int> () { 86, 68, 73, 97 } } }; //创建第二个数据源 var teachers = new List<Teacher>() { new Teacher () { Age = 35, City = "梦里", Name = "啵哆" }, new Teacher () { Age = 28, City = "云南", Name = "小红" }, new Teacher () { Age = 38, City = "河南", Name = "丽丽" } }; //创建查询 var peopleInDreams = (from student in students where student.City == "梦里" select student.Name) .Concat(from teacher in teachers where teacher.City == "梦里" select teacher.Name); //执行查询 foreach (var person in peopleInDreams) { Console.WriteLine(person); } Console.Read(); }
结果
小叁
啵哆
1. 若要只选择源元素的一个成员,请使用点运算。
var query = from cust in Customers select cust.City;
2. 若要创建包含源元素的多个属性的元素,可以使用具有命名对象或匿名类型的对象初始值设定项。
var query = from cust in Customer select new {Name = cust.Name, City = cust.City};
//创建数据源 var students = new List<Student>() { new Student() { Age = 18, Name = "小A", Scores = new List<int>() {88,85,74,66 } }, new Student() { Age = 35, Name = "小B", Scores = new List<int>() {88,85,74,66 } }, new Student() { Age = 28, Name = "小啥", Scores = new List<int>() {88,85,74,66 } } }; //创建查询 var studentsToXml = new XElement("Root", from student in students let x = $"{student.Scores[0]},{student.Scores[1]},{student.Scores[2]},{student.Scores[3]}" select new XElement("student", new XElement("Name", student.Name), new XElement("Age", student.Age), new XElement("Scores", x)) ); //执行查询 Console.WriteLine(studentsToXml);
输出序列可能不包含源序列的任何元素或元素属性。
输出可能是通过将源元素用作输入参数计算出的值的序列。
//数据源 double[] radii = { 1, 2, 3 }; //创建查询 var query = from radius in radii select $"{radius * radius * 3.14}"; //执行查询 foreach (var i in query) { Console.WriteLine(i); }
到此这篇关于C#中Linq用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。