大家好,欢迎来到IT知识分享网。
什么是linq
语言集成查询 (LINQ) 是一组基于将查询功能直接集成到 C# 语言中的技术的名称。传统上,对数据的查询表示为简单的字符串,在编译时没有类型检查或 IntelliSense 支持。此外,您必须为每种类型的数据源学习不同的查询语言:SQL 数据库、XML 文档、各种 Web 服务等等。使用 LINQ,查询是一流的语言结构,就像类、方法、事件一样。您可以使用语言关键字和熟悉的运算符针对强类型的对象集合编写查询。LINQ 系列技术为对象 (LINQ to Objects)、关系数据库 (LINQ to SQL) 和 XML (LINQ to XML) 提供一致的查询体验。
之前我们查询集合中的数据一般会使用for或foreach语句来进行查询,Linq 使用查询表达式来进行查询,Linq 表达式比之前用for或forach的方式更加简洁,比较容易添加筛选条件。
将下列int集合整体每个元素扩大10倍
var num = new List<int>() { 1,2,3,4,5}; IEnumerable<int> query = num.Select(n => n * 10); foreach (int n in query) Console.WriteLine(n);
从上面的例子可以看出,linq集合在查询是简单了很多,并且很容易添加筛选条件。
linq原理
编译器是如何处理这些查询表达式的呢,为了理解好这个问题就要先解释一下linq的底层思想。
1.序列
序列是linq的基础。序列是通过过IEnumerable和IEnumerable<T>接口进行封装,如果某个类型实现了IEnumerable接口,就意味着它可以被迭代访问。序列就像一个数据的传送带,每次只能获取一个,知道你不想传了或者序列中没有数据了。序列和其他集合数据结构(比如列表和数组)之间最大的区别就是,当你从序列读取数据的时候,通常不知道还有多少数据项等待读取,或者不能访问任意的数据项——只能是当前的这个。在你看到一个linq查询表达式的时候,应该要想到它所涉及的序列:一开始总是存在至少一个序列,且通常在中间过程会转换为其他序列,也可能和更多的序列连接在一起。
举个例子,获取成年人姓名的表达式
var names = from person in people where person.Age >= 18 select person.Name;
foreach (var n in names)
Console.WriteLine(n);
然后讲这个表达式分解成独立的步骤:每一个箭头代表一个序列。每个框都代表查询表达式的一个步骤。我们获取他整个家庭成员(用Person对象表示)。接着经过过滤后,序列就只包含成人了(还是用Person对象表示)。而最终的结果以字符串形式包含这些成人的名字。每个步骤就是得到一个序列,在序列上应用操作以生成新的序列。结果不是字符串”Holly”和”Jon”——而是IEnumerable <String>,这样,在从里面一个接一个获取元素的时候,将首先生成”Holly”,其次得到”Jon”。
查询操作并不是在查询运算符定义的时候执行,而是在真正使用集合中的数据时才执行(如:在遍历集合时调用MoveNext方法和Current检查),再举个简单的例子
var num = new List<int>(); num.Add(1); IEnumerable<int> query = num.Select(n => n * 10); foreach (int n in query) Console.WriteLine(n); num.Add(2); foreach (int n in query) Console.WriteLine(n);
输出的结果是10 20
绝大部分标准的LINQ查询运算符都具有延迟加载这种特性,但也有例外:
- 那些返回单个元素或返回一个数值的运算符,如First或Count。
- 转换运算符:ToArray,ToList,ToDictonnary,ToLookup。
以上这些运算符都会触发LINQ语句立即执行,因为它们的返回值类型不支持延迟加载。
3.标准查询操作符
var list = query.Where(m => m.PID == corpID && m.type == 8);
2.OrderBy
var list = query.Where(m => m.PID == corpID && m.type == 8).OrderBy(m => m.PID);
3.join连接
var q2 = from u in dataContext.useinfo join d in dataContext.useDetails on u.id equals d.id select u; //join时必须将join后的表into到一个新的变量XX中,然后要用XX.DefaultIfEmpty()表示外连接。 //DefaultIfEmpty使用了泛型中的default关键字。default关键字对于引用类型将返回null,而对于值类型则返回0。 //对于结构体类型,则会根据其成员类型将它们相应地初始化为null(引用类型)或0(值类型) var q3 = from u in dataContext.useinfo join d in dataContext.useDetails on u.id equals d.id into f from c in f.DefaultIfEmpty() select c;
附件:linq源码 https://github.com/dotnet/runtime
【参考】《深入理解C#》
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30482.html