在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
LINQ什么是LINQ在关系型数据库系统中,数据被组织放入规范化很好的表中,并且通过简单且强大的SQL语言来进行访问。因为数据在表中遵从某些严格的规则,所以SQL可以和它们很好的配合使用。
例:LINQ示例 class Program { static void Main() { int[] numbers={2,12,5,15}; IEnumerable<int> lowNums= from n in numbers where n<10 select n; foreach(var x in lowNums) { Console.WriteLine(x); } } } LINQ提供程序在之前的示例中,数据源只是int数组,它是程序在内存中的对象。然而,LINQ还可以和各种类型的数据源一起工作。然而,对于每种数据源类型,在其背后一定有根据该数据源类型实现LINQ查询的代码模块。这些代码模块叫做LINQ提供程序(provider)。
本章中,我们主要介绍LINQ并解释如何将其用于程序对象(LINQ to Object)和XML(LINQ to XML),其他细节和用法不做讨论。 匿名类型在介绍LINQ查询特性的细节前,我们先学习一个允许我们创建无名类类型的特性。匿名类型(anonymous type)经常用于LINQ查询的结果中。 没有类名 ↓ new {FieldProp=InitExpr,FieldProp=InitExpr,...} ↑ 成员初始化语句 例:创建和使用匿名类型的示例。 class Program { static void Main() { 必须使用var ↓ var student=new{Name="Mary Jones",Age=19,Major="History"}; Console.WriteLine("{0},Age {1},Major: {2}",student.Name,student.Age,studeng.Major); } } 需要了解的有关匿名类型的重要事项如下。
当编译器遇到匿名类型的对象初始化语句时,它创建一个有名字的新类类型。低于每个成员初始化语句,它推断其类型并创建一个只读属性来访问它的值。属性和成员初始化语句具有相同名字。匿名类型被构造后,编译器创建了这个类型的对象。 var student=new{Age=19,Other.Name,Major}; 例:使用3总初始化语句。注意,投影初始化语句必须定义在匿名类型声明之前。 class Other { static public string Name="Mary Jones"; } class Program { static void Main() { string Major="History"; var student=new{Age=19,Other.Name,Major}; Console.WriteLine("{0},Age {1},Major: {2}",student.Name,student.Age,studeng.Major); } } 如果编译器遇到了另一个具有相同的参数名、相同的推断类型和相同顺序的匿名类型,它会重用这个类型并直接创建新的实例,不会创建新的匿名类型。 方法语法和查询语法我们在写LINQ查询时可以使用两种形式的语法:方法语法和查询语法。
方法语法是命令式(imperative)的,它指明了查询方法调用的顺序。 例:方法语法和查询语法演示 class Program { static void Main() { int[] numbers={2,5,28,31,17,16,42}; var numsQuery=from n in numbers //查询语法 where n<20 select n; var numsMethod=numbers.Where(x=>x<20); //方法语法 int numsCount=(from n in numbers //两种形式组合 where n<20 select n).Count(); foreach(var x in numsQuery) { Console.Write("{0}, ",x); } Console.WriteLine(); foreach(var x in numsMethod) { Console.Write("{0}, ",x); } Console.WriteLine(); Console.WriteLine(numsCount); } } 查询变量LINQ查询可以返回两种类型的结果–可以是一个枚举(可枚举的一组数据,不是枚举类型),它满足查询参数的项列表;也可以是一个叫做标量(scalar)的单一值,它是满足查询条件的结果的某种摘要形式。 例:查询变量示例 int[] numbers={2,5,28}; IEnumerable<int> lowNums=from n in numbers //返回枚举数 where n<20 select n; int numsCount=(from n in numbers //返回一个整数 where n<20 select n).Count(); 理解查询变量的用法很重要。在执行前面的代码后,lowNums查询变量不会包含查询的结果。相反,编译器会创建能够执行这个查询的代码。
查询表达式的结构查询表达式由查询体后的from子句组成。有关查询表达式需要了解一些重要事项:
from子句from子句指定了要作为数据源使用的数据集合。它还引入了迭代变量。有关from子句的要点如下:
from Type Item in Items 下图演示了from子句的语法。类型说明符是可选的。可以有任意多个join子句。 尽管LINQ的from子句和foreach语句非常相似,但主要不同点如下:
join子句LINQ中的join子句和SQL中的JOIN(联结)子句相似。不同的是,我们现在不但可以在数据库的表上进行联结,还可以在集合对象上进行该操作。如果你不熟悉联结,那么下面的内容会帮你理清思路。
联结语法如下 关键字 关键字 关键字 关键字 ↓ ↓ ↓ ↓ join Identifier in Collection2 on Field1 equals Field1 ↑ 指定另外的集合和ID引用它 var query=from s in students join c in studentsInCourses on s.StID equals c.StID 什么是联结LINQ中的join接受两个集合然后创建一个新的集合,每个元素包含两个原始集合中的原始成员。 例:联结示例 class Program { public class Student { public int StID; public string LastName; } public class CourseStudent { public string CourseName; public int StID; } static Student[] students=new Student[]{ new Student{StID=1,LastName="Carson"}, new Student{StID=2,LastName="Klassen"}, new Student{StID=3,LastName="Fleming"}, }; static CourseStudent[] studentsInCourses=new CourseStudent[]{ new CourseStudent{CourseName="Art",StID=1}, new CourseStudent{CourseName="Art",StID=2}, new CourseStudent{CourseName="History",StID=1}, new CourseStudent{CourseName="History",StID=3}, new CourseStudent{CourseName="Physics",StID=3}, } static void Main() { var query=from s in students join c in studentsInCourses on s.StID equals c.STID where c.CourseName=="History" select.LastName; foreach(var q in query) { Console.WriteLine("Student taking History:{0}",q); } } } 查询主体中的from…let…where片段可选的from…let…where部分是查询主体的第一部分,可以由任意数量的3个子句来组合–from子句、let子句和where子句。 from子句查询表达式从必需的from子句开始,后面跟查询主体。主体本身可以从任何数量的其他from子句开始,每个from子句都指定了一个额外的源数据集合并引入了要在之后运算的迭代变量,所有from子句的语法和含义都一样。 例:from子句示例 class Program { static void Main() { var groupA=new[]{3,4,5,6}; var groupA=new[]{6,7,8,9}; var someInts=from a in groupA from b in groupB where a>4&&b<=8 select new{a,b,sum=a+b};//匿名类型对象 foreach(var a in someInts) { Console.WriteLine(a); } } } let子句let子句接受一个表达式的运算并且把它赋值给一个需要在其他运算中使用的标识符。let子句的语法如下: let Identifier=Expression 例:let子句示例 class Program { static void Main() { var groupA=new[]{3,4,5,6}; var groupA=new[]{6,7,8,9}; var someInts=from a in groupA from b in groupB let sum=a+b //在新的变量中保存结果 where sum==12 select new{a,b,sum}; foreach(var a in someInts) { Console.WriteLine(a); } } } where子句where子句根据之后的运算来筛选指定项。 例:where子句示例 class Program { static void Main() { var groupA=new[]{3,4,5,6}; var groupA=new[]{6,7,8,9}; var someInts=from a in groupA from b in groupB let sum=a+b where sum>=11 ←条件1 where a==4 ←条件2 select new{a,b,sum}; foreach(var a in someInts) { Console.WriteLine(a); } } } orderby子句orderby子句根据表达式按顺序返回结果项。
例:按照学生年龄排序 class Program { static void Main() { var students=new[] { new{LName="Jones",FName="Mary",Age=19,Major="History"}, new{LName="Smith",FName="Bob",Age=20,Major="CompSci"}, new{LName="Fleming",FName="Carol",Age=21,Major="History"}, }; var query=from student in students orderby student.Age select student; foreach(var s in query) { Console.WriteLine("{0},{1}: {2} - {3}",s.LName,s.FName,s.Age,s.Major); } } } select…group子句select…group子句的功能如下所示。
例:select整个数据项 using System; using System.Linq; class Program { static void Main() { var students=new[] { new{LName="Jones",FName="Mary",Age=19,Major="History"}, new{LName="Smith",FName="Bob",Age=20,Major="CompSci"}, new{LName="Fleming",FName="Carol",Age=21,Major="History"}, }; var query=from s in students select s; foreach(var s in query) { Console.WriteLine("{0},{1}: {2} , {3}",s.LName,s.FName,s.Age,s.Major); } } } var query=from s in students select s.LName; foreach(var s in query) { Console.WriteLine(s); } 查询中的匿名类型查询结果可以由原始集合的项、项的某些字段或匿名类型组成。 using System; using System.Linq; class Program { static void Main() { var students=new[] { new{LName="Jones",FName="Mary",Age=19,Major="History"}, new{LName="Smith",FName="Bob",Age=20,Major="CompSci"}, new{LName="Fleming",FName="Carol",Age=21,Major="History"}, }; var query=from s in students select new{s.LName,s.FName,s.Major}; foreach(var s in query) { Console.WriteLine("{0} {1} -- {2} , {3}",s.FName,s.LName,s.Major); } } } group子句group子句把select的对象根据一些标准进行分组。例如,之前示例的学士数组,程序可以根据它们的主修课程进行分组。
例:根据学士的主修课程进行分组 using System; using System.Linq; class Program { static void Main() { var students=new[] { new{LName="Jones",FName="Mary",Age=19,Major="History"}, new{LName="Smith",FName="Bob",Age=20,Major="CompSci"}, new{LName="Fleming",FName="Carol",Age=21,Major="History"}, }; var query=from s in students group s by s.Major; foreach(var s in query) { Console.WriteLine("{0}",s.Key); foreach(var t in s) { Console.WriteLine(" {0},{1}",t.LName,t.FName); } } } } 查询延续:into子句查询延续子句可以接受查询的一部分结果并赋予一个名字,从而可以在查询的另一部分中使用。 class Program { static void Main() { var groupA=new[]{3,4,5,6}; var groupA=new[]{6,7,8,9}; var someInts=from a in groupA join b in groupB on a equals b into groupAandB from c in groupAandB select c; foreach(var a in someInts) { Console.WriteLine(a); } } } 输出:6 标准查询运算符标准查询运算符由一系列API方法组成,它能让我们查询任何.NET数组或集合。
例:Sum和Count运算符的使用 class Program { static int[] numbers=new int[]{2,4,6}; static void Main() { int total=numbers.Sum(); int howMany=number.Count(); Console.WriteLine("Total: {0},Count: {1}",total,howMany); } } 标准查询运算符可用来操作一个或多个序列。序列指实现了IEnumerable<>接口的类型,包括List<>、Dictionary<>、Stack<>、Array等。 标准查询运算符的签名System.Linq.Enumerable类声明了标准查询运算符方法。这些方法不仅是一些方法,它们是扩展了 例:3个标准查询运算符的签名 始终是public static 名字和泛型参数 第一个参数 ↓ ↓ ↓ public static int Count<T>(this IEnumerable<T> source); public static T First<T>(this IEnumerable<T> source); public static IEnumerable<T> Where<T>(this IEnumerable<T> source,...); 例:直接调用扩展方法和将其作为扩展进行调用的不同 using System.Linq; ... static void Main() { int[] intArray=new int[]{3,4,5,6,7,9}; //方法语法 var count1=Enumerable.Count(intArray); var firstNum1=Enumerable.First(intArray) //扩展语法 var count2=intArray.Count(); var firstNum2=intArrya.First(); Console.WriteLine("Count: {0},FirstNumber: {1}",count1,firstNum1); Console.WriteLine("Count: {0},FirstNumber: {1}",count2,firstNum2); } 查询表达式和标准查询运算符查询表达式和方法语法可以组合。编译器把每个查询表达式翻译成标准查询运算符的形式。 class Program { static void Main() { var numbers=new int[]{2,6,4,8,10}; int howMany(from n in numbers where n<7 select n).Count(); Console.WriteLine("Count: {0}",howMany); } } 将委托作为参数前面我们看到,每个运算符的第一个参数是 为了解释这一点,我们首先从演示Count运算符的几种使用方式的示例开始。 public static int Count<T>(this IEnumerable<T> source); 然而,假设我们希望看看数组中奇数元素的总数。Count方法必须能够检测整数是否为奇数。 public static int Count<T>(this IEnumerable<T> source,Func<T,bool> predicate); class Program { static void Main() { int[] intArray=new int[] {3,4,5,6,7,9}; var countOdd=intArray.Count(n=>n%2!=0); Console.WriteLine("Count of odd numbers: {0}",countOdd); } } LIN |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论