单个form子句
string[] values = { "LINQ学习", "LINQ基本语句", "from子句", "单个from子句" }; var value = from v in values where v.IndexOf("LINQ") > -1 //包含字符串 select new { v, v.Length };//返回自定义数组 foreach (var n in value) { Response.Write(n.v+"###"+n.Length); } 使用LINQ查询ArrayList ArrayList gList = new ArrayList(); gList.Add(new GustInfo { Name="DebugLZQ", Age=26, Tel="88888888"}); gList.Add(new GustInfo { Name="博客园",Age=6, Tel ="666666"}); gList.Add(new GustInfo { Name = "M&MSoft", Age =9, Tel = "55555" });var query = from GustInfo gust in gList
where gust.Age > 9 select gust;//范围变量gust制定了数据类型 foreach (GustInfo g in query) { Console.WriteLine("{0} 年龄:{1} 电话:{2}",g.Name,g.Age,g.Tel ); }//复合from子句
List<GustInfo1> gList2 = new List<GustInfo1>() { new GustInfo1{ Name="DebugLZQ",Age=26,TelTable=new List<string>(){"8888888","138******"}}, new GustInfo1{ Name="博客园",Age=6,TelTable =new List<string>(){"666666","138******"}}, new GustInfo1{ Name="M&MSoft",Age=9,TelTable=new List<string>(){"55555","138******"}} };//gust、tel都是查询变量,作用域为当前查询语句!!!
var query2 = from gust in gList2 from tel in gust.TelTable where tel.IndexOf("8888888") > -1 select gust; foreach (var g in query2) { Response.Write(g.Name+" 年龄"+ g.Age); foreach (var t in g.TelTable) { Response.Write("电话:"+t); } }
//4多个from子句
ArrayList gList = new ArrayList(); gList.Add(new GustInfo { Name = "DebugLZQ", Age = 26, Tel = "88888888" }); gList.Add(new GustInfo { Name = "博客园", Age = 6, Tel = "666666" }); gList.Add(new GustInfo { Name = "M&MSoft", Age = 9, Tel = "55555" }); List<GustInfo1> gList2 = new List<GustInfo1>() { new GustInfo1{ Name="DebugLZQ",Age=26,TelTable=new List<string>(){"8888888","138******"}}, new GustInfo1{ Name="博客园",Age=6,TelTable =new List<string>(){"666666","138******"}}, new GustInfo1{ Name="M&MSoft",Age=9,TelTable=new List<string>(){"55555","138******"}} }; //4多个from子句 var query3 = from GustInfo gust in gListwhere gust.Age > 6from GustInfo1 gust2 in gList2where gust2.Age > 9 select new { gust, gust2 };//查询结果定制 foreach (var g in query3) { Response.Write(g.gust.Name + "###" + g.gust2.Name); }where子句使用自定义函数
protected void whereExpDemo(object sender, EventArgs e) { List<GustInfo> clist = new List<GustInfo> { new GustInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new GustInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new GustInfo{ Name="令狐冲", Age=23, Tel ="1380524****"} };//查询名字是3个字并且姓“令”的客户
var query = from customer in clist where (customer.Name.Length == 3 && CheckName(customer.Name)) select customer;foreach (var ci in query)
{ Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); } } private bool CheckName(string name) { if (name.Substring(0, 1) == "令") return true; else return false; }where 数组
List<CustomerInfo> clist = new List<CustomerInfo> { new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="令狐冲", Age=23, Tel ="1380524****"} };//定义动态的谓词数组,这个数组应该由实际运行环境生成
string[] names = { "令狐冲", "任盈盈", "杨过", "小龙女", "欧阳晓晓" };//查询在给定谓词数组里存在的客户
var query = from customer in clist where names.Contains(customer.Name) select customer;foreach (var ci in query)
{ Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); }
4. select子句
LINQ表达式的结果是使用select子句获得的。select子句可以对数据进行转换,这个过程称为“投影”。select子句产生的类容,取决于前面的所有子句及其自身表达式执行后的结果。
4.1 输出查询结果
最简单的select就是直接输出from子句建立的那个范围变量:var query = from customer in clist
where names.Contains(customer.Name) select customer;也可以输出范围变量类型中得某个属性:select customer.Name;
或者修改一下再输出:select customer.Name.Replace("gg","mm");
或者干脆使用一个自定义的函数,把范围变量传进去,输出处理后的结果:select MyFunction(customer.Name);
4.2 对查询结果进行投影
public class MyCustomerInfo
{ public string Name { get; set; } public string Tel { get; set; } } private void whereExpDemo() { List<CustomerInfo> clist = new List<CustomerInfo> { new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="令狐冲", Age=23, Tel ="1380524****"} };//定义动态的谓词数组,这个数组应该由实际运行环境生成
string[] names = { "令狐冲", "任盈盈", "杨过", "小龙女", "欧阳晓晓" };//查询在给定谓词数组里存在的客户
var query = from customer in clist where customer.Age < 30select new MyCustomerInfo { Name = customer.Name, Tel = customer.Tel };foreach (var ci in query)
{ Console.WriteLine("姓名:{0} 电话:{1} 类型{2}", ci.Name, ci.Tel,ci.GetType().FullName); } }
5. group子句
按照语法的规定,LINQ表达式必须以from子句开头,以select或group子句结束,所以除了使用select子句外,也可以使用guoup子句来返回元素分组后的结果。group子句返回的是一个IGrouping<TKey,TElement>泛型接口的对象集合,下面先了解下这个接口。
5.1 IGrouping<TKey,TElement>泛型接口
这个接口表示具有公共键的对象集合,它的原型如下:
public interface IGrouping: IEnumerable , IEnumerable
TKey是键的对象类型,在用于group子句的时候,数据类型会有编译器推断出来,它一般用于存储分组的键值;TElement是指的对象类型,用于存储分组的结果,变量基于这个接口的类型就是遍历这个值。
5.2 分组查询
分组查询对于关系型数据库是非常常见的一种操作,但在没有LINQ之前,对内存的对象进行分组却是一件非常麻烦的事情。现在,在LINQ表达式中只需要使用group子句就可以轻松完成对内存对象的分组。List<CustomerInfo> clist = new List<CustomerInfo> {
new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="欧阳锦鹏", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官无忌", Age=23, Tel ="1380524****"} };//按照名字的前2个字进行分组
var query = from customer in clistgroup customer by customer.Name.Substring(0, 2);foreach (IGrouping<string,CustomerInfo> group in query)
{ Console.WriteLine("分组键:{0}",group.Key); foreach (var ci in group) { Console.WriteLine("姓名:{0} 电话:{1}", ci.Name, ci.Tel); } Console.WriteLine("***************************************"); }上例代码,按照form子句建立的范围变量customer的Name属性的前两个字作为键值进行分组。所以TKey的类型是一个字符串类型。
//按照年龄是否大于20分组
var query = from customer in clistgroup customer by customer.Age > 20;foreach (var group in query)
{ Console.WriteLine("分组键:{0}",group.Key); foreach (var ci in group) { Console.WriteLine("姓名:{0} 电话:{1}", ci.Name, ci.Tel); } Console.WriteLine("***************************************"); } group子句用了一个布尔表达式,所以IGrouping<TKey,TElement>的TKey变成了一个bool型。并且循环遍历的时候可以用var代替IGrouping的声明:foreach (var group in query)
6. into子句
into子句作为一个临时标识符,用于select,group,join子句中。
List<CustomerInfo> clist = new List<CustomerInfo> { new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="欧阳锦鹏", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官无忌", Age=23, Tel ="1380524****"} };//按照名字的前两个字进行分组,再用分组Key进行排序
var query = from customer in clist group customer by customer.Name.Substring(0, 2) into gpcustomer orderby gpcustomer.Key descending select gpcustomer; Console.WriteLine("into 用于group子句"); foreach (var group in query) { Console.WriteLine("分组键:{0}", group.Key); foreach (var ci in group) { Console.WriteLine("姓名:{0} 电话:{1}", ci.Name, ci.Tel); } Console.WriteLine("***************************************"); }var query2 = from customer in clist
select new { NewName = customer.Name, NewAge = customer.Age } into newCustomer orderby newCustomer.NewAge select newCustomer;Console.WriteLine("into 用于select子句");
foreach (var ci in query2) { Console.WriteLine("{0} 年龄:{1}", ci.NewName, ci.NewAge); }
7. 排序子句
LINQ可以按元素的一个或多个属性对元素进行排序。LINQ表达式的排序方式分为OrderBy、OrderByDescending、ThenBy、ThenByDescending这四种。
7.1 OrderBy和OrderByDescending
OrderBy用于按元素的值进行升序,语法:orderby 用于排序的元素的表达式
OrderByDescending用于按元素的值进行降序,语法:orderby 用于排序的元素的表达式 descending
List<CustomerInfo> clist = new List<CustomerInfo> {
new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="欧阳锦鹏", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官无忌", Age=23, Tel ="1380524****"} };//按照年龄升序
var query = from customer in clist orderby customer.Age select customer; Console.WriteLine("按年龄升序排列"); foreach (var ci in query) { Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); } //按照年龄降序 var query2 = from customer in clist orderby customer.Age descending select customer; Console.WriteLine("\n按年龄降序排列"); foreach (var ci in query2) { Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); }
7.2 ThenBy和ThenByDescending
ThenBy和ThenByDescending用于对元素进行次要排序。基本语法:orderby 用于排序的元素表达式,用于排序的元素表达式
orderby 用于排序的元素表达式,用于排序的元素表达式 descending List<CustomerInfo> clist = new List<CustomerInfo> { new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="郭靖", Age=17, Tel ="1330708****"}, new CustomerInfo{ Name="黄蓉", Age=17, Tel ="1300524****"} };//按照年龄升序,再按名字的字数次要排序
var query = from customer in clistorderby customer.Age,customer.Name.Length select customer; Console.WriteLine("按年龄排列,按名字字数进行次要排序"); foreach (var ci in query) { Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); } //按照年龄升序,再按名字的字数降序次要排序 var query2 = from customer in clistorderby customer.Age, customer.Name.Length descending select customer; Console.WriteLine("\n按年龄排列,按名字字数进行降序次要排序"); foreach (var ci in query2) { Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); } //按照年龄升序,再按名字的字数降序要排序,在按电话号码进行第三条件排序 var query3 = from customer in clistorderby customer.Age, customer.Name.Length,customer.Tel select customer; Console.WriteLine("\n按年龄,名字字数,电话号码排序"); foreach (var ci in query3) { Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); }8. let子句
let子句用于在LINQ表达式中存储子表达式的计算结果。let子句创建一个范围变量来存储结果,变量被创建后,不能修改或把其他表达式的结果重新赋值给它。此范围变量可以再后续的LINQ子句中使用。
List<CustomerInfo> clist = new List<CustomerInfo> { new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="郭靖", Age=17, Tel ="1330708****"}, new CustomerInfo{ Name="黄蓉", Age=17, Tel ="1300524****"} };//姓“郭”或“黄”的客户
var query = from customer in clistlet g = customer.Name.Substring(0,1) where g == "郭" || g == "黄" select customer; foreach (var ci in query) { Console.WriteLine("姓名:{0} 年龄:{1} 电话:{2}", ci.Name, ci.Age, ci.Tel); }使用let 建立了个范围变量,这个范围变量在后续的where子句中使用,如果不使用let子句,where子句的表达式将写成这样:
where customer.Name.Substring(0, 1) == "郭" || customer.Name.Substring(0, 1) == "黄"
9. join子句
如果一个数据源中元素的某个属性可以跟另一个数据源中元素的属性进行相等比较,那么这两个数据源可以用join子句进行关联。jion子句用equals关键字进行比较,而不是常见的==。
List<CustomerInfo> clist = new List<CustomerInfo>
{ new CustomerInfo{ Name="欧阳晓晓", Age=35, Tel ="1330708****"}, new CustomerInfo{ Name="上官飘飘", Age=17, Tel ="1592842****"}, new CustomerInfo{ Name="郭靖", Age=17, Tel ="1330708****"}, new CustomerInfo{ Name="黄蓉", Age=17, Tel ="1300524****"} };List<CustomerTitle> titleList = new List<CustomerTitle>
{ new CustomerTitle{ Name="欧阳晓晓", Title="歌手"}, new CustomerTitle{ Name="郭靖", Title="大侠"}, new CustomerTitle{ Name="郭靖", Title="洪七公徒弟"}, new CustomerTitle{ Name="黄蓉", Title="才女"}, new CustomerTitle{ Name="黄蓉", Title="丐帮帮主"} };//根据姓名进行内部联接
Console.WriteLine("内部联接"); var query = from customer in clist join title in titleListon customer.Name equals title.Name select new { Name = customer.Name, Age = customer.Age, Title = title.Title }; foreach (var ci in query) { Console.WriteLine("姓名:{0} 年龄:{1} {2}", ci.Name, ci.Age, ci.Title); } //根据姓名进行分组联接 Console.WriteLine("\n根据姓名进行分组联接"); var query2 = from customer in clist join title in titleList on customer.Name equals title.Name into tgroup select new { Name = customer.Name, Titles = tgroup }; foreach (var g in query2) { Console.WriteLine(g.Name); foreach (var g2 in g.Titles) { Console.WriteLine(" {0}", g2.Title); } } //根据姓名进行 左外部联接 Console.WriteLine("\n左外部联接"); var query3 = from customer in clist join title in titleList on customer.Name equals title.Name into tgroupfrom subTitle in tgroup.DefaultIfEmpty()select new { Name = customer.Name, Title = (subTitle == null ? "空缺" : subTitle.Title) }; foreach (var ci in query3) { Console.WriteLine("姓名:{0} {1} ", ci.Name, ci.Title); }