LINQ( Language Integrated Query )即语言集成查询
LINQ 是一组语言特性和API,使得你可以使用统一的方式编写各种查询。查询的对象包括XML、对象集合、SQL Server 数据库等等。
LINQ 主要包含以下三部分:
LINQ to Objects 主要负责对象的查询
LINQ to XML 主要负责 XML 的查询
LINQ to ADO.NET 主要负责数据库的查询
LINQ to SQL
LINQ to DataSet
LINQ to Entities
如图:
LINQ查询的两种方式
1、Method Syntax 方法语法:利用扩展方法和Lamda表达式方式查询
2、Query Syntax 查询语法:标准的LINQ查询运算符(优先选择)
class QueryVMethodSyntax
{
static void Main()
{
int[] numbers = { 5, 10, 8, 3, 6, 12};
//查询语法:
IEnumerable<int> numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
//方法语法:
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
foreach (int i in numQuery1)
{
Console.Write(i + " ");
}
Console.WriteLine(System.Environment.NewLine);
foreach (int i in numQuery2)
{
Console.Write(i + " ");
}
// Keep the console open in debug mode.
Console.WriteLine(System.Environment.NewLine);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
/*
Output:
6 8 10 12
6 8 10 12
*/
一、初步体验
int[] arr = { 20, 4, 51 };
//得到数组中大于50的数
IEnumerable ie = arr.Select(p => p).Where(p => p > 50);
//输出
IEnumerator result = ie.GetEnumerator();
while (result.MoveNext())
{
Response.Write(result.Current);
}
(1)、IEnumerable接口,只包含一个抽象的方法GetEnumerator(),它返回一个可用于循环访问集合的IEnumerator对象。
(2)、IEnumerator 集合访问器,没有它,就不能使用foreach语句遍历集合或数组。
IEnumerator接口定义了一个Current属性,MoveNext和Reset两个方法。
Current属性,来获取当前集合中的项吧。
MoveNext方法只是将游标的内部位置向前移动(就是移到一下个元素而已),要想进行循环遍历,不向前移动一下怎么行呢?
拓展方法是静态方法,必须写在静态类中。
//拓展类只能是静态类
public static class ExtraClass
{
//string的拓展方法--特殊的静态方法(this表示为string类型添加特殊的方法ToPascal)
public static string ToPascal(this string s)
{
return s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();
}
//IEnumerable的拓展方法
public static string Print(this IEnumerable<int> ie)
{
string str = "";
IEnumerator<int> result= ie.GetEnumerator();
while (result.MoveNext())
{
str+=result.Current+"|";
}
return str;
}
}
string str = "werwerwerw";
Console.WriteLine(str.ToPascal());
历史:FrameWork1.0 委托---->FrameWork2.0 匿名方法--->FrameWork3.5 匿名方法--->Lambda表达式
1、FrameWork1.0 委托
public delegate string deleTransfer(string s);//注意方法的签名
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//委托指向方法名
deleTransfer trans = new deleTransfer(ToPascal);
Response.Write(trans("FrameWork1.0 委托"));
}
public string ToPascal(string s)
{
return s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();
}
}
注:方法名可以随便
2、FrameWork2.0 匿名方法
public delegate string deleTransfer(string s);
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
deleTransfer trans = delegate(string s){return s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();};
Response.Write(trans("FrameWork2.0 匿名方法"));
}
}
3、FrameWork3.5 匿名方法
public delegate string deleTransfer(string s);
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
deleTransfer trans = (s)=>{return s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();};
Response.Write(trans("FrameWork3.5 匿名方法"));
}
}
4、Lambda表达式
public delegate string deleTransfer(string s);
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{ //语法:(参数列表)=>{方法体};
deleTransfer trans = s=>s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();
Response.Write(trans("Lambda表达式"));
}
}
四、LINQ基本方法语法方式
1、select/where 语句
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<string> persons = new List<string>();
persons.Add("zhang shan");
persons.Add("zhang shan feng");
persons.Add("li si");
persons.Add("wang wu");
//查询名称以zhang开头
//var result = (from p in persons select p).Where(p => p.StartsWith("zhang"));
var result = persons.Select(p => p).Where(p => p.StartsWith("zhang"));
Label1.Text = result.Print();
}
}
//拓展类只能是静态类
public static class ExtraClassA
{
//IEnumerable的拓展方法
public static string Print(this IEnumerable<string> ie)
{
string str = "";
IEnumerator<string> result = ie.GetEnumerator();
while (result.MoveNext())
{
str += result.Current + "|";
}
return str;
}
}
2、OrderBy排序
//var result = persons.OrderBy(p => p);
//按名字最后一个字母排序
var result = persons.OrderBy(p => p.Substring(p.Length - 1, 1));
//降序
var result=persons.OrderByDescending(p=>p)
3、GroupBy分组
List<string> persons = new List<string>();
persons.Add("zhang shan");
persons.Add("zhang shan feng");
persons.Add("li si");
persons.Add("wang wu");
//按姓名分组,取出姓名中空格前的部分
var result = persons.GroupBy(p => p.Split(new char[] { ' ' })[0]);
foreach (var group in result)//外层循环得到分组
{
Response.Write("姓:" + group.Key + "<br>");
foreach (var name in group)//内层循环得到分组中的项
{
Response.Write(" " + name + "<br>");
}
}
LINQ 的更多资源
官方网站
http://msdn2.microsoft.com/zh-cn/netframework/aa904594(en-us).aspx
Hooked On LINQ
http://www.hookedonlinq.com/
五、高级查询方法
1、聚合类
Count,Max/Min,Average,Sum
//Count 返回集合项的数目
int count = (from p in foxRiver8
where p.Age <= 30
select p).Count();//混合模式
int count = foxRiver8
.Where(p => p.Age <= 30)
.Count();//纯粹查询方法模式
//Max 返回集合中的最大值
int maxAge = (from p in foxRiver8
select p.Age).Max();
int maxAge = foxRiver8
.Select(p => p.Age)
.Max();
//Average 返回集合的平均值
double averageAge = (from p in foxRiver8
select p.Age).Average();
double averageAge = foxRiver8
.Select(p => p.Age)
.Average();
//Sum 返回集合的总和
Int sumAge = (from p in foxRiver8
select p.Age).Sum();
int sumAge = foxRiver8
.Select(p => p.Age)
.Sum();
2、排序类
ThenBy
//ThenBy 提供复合排序条件
var q = foxRiver8
.OrderBy(p => p.FirstName)
.ThenBy(p => p.LasName)
.ThenBy(p => p.Age);//查询方法
var q = from p in foxRiver8
orderby p.FirstName, p.LasName, p.Age
select p;//查询语句
3、分区类
Take,TakeWhile,Skip,SkipWhile
Take 提取指定数量的项
Skip 跳过指定数量的项并获取剩余的项
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var q = numbers.Skip(1).Take(3);//跳过前1条记录,连续提取3条记录,得到 2 3 4
foreach (var item in q)
{
Console.WriteLine(item);
}
TakeWhile 根据指定条件提取项
SkipWhile 根据指定条件跳过项
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var q = numbers.SkipWhile(i => i % 3 != 0)
.TakeWhile(i => i % 2 != 0);
foreach (var item in q)
{
Console.WriteLine(item);
}
请判断以下代码输出结果是什么?请判断以下代码输出结果是什么?
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var q = numbers.Skip(1).Take(3).Skip(1).Take(2);
foreach (var item in q)
{
Console.WriteLine(item);
}
输出: 3 4
4、集合类
Distinct
//Distinct 去掉集合中的重复项
int[] factorsOf300 = { 2, 2, 3, 5, 5 };
var uniqueFactors = factorsOf300.Distinct();//输出: 2 3 5
5、生成类
Range, Repeat
//Range 生成一个整数序列
var numbers =Enumerable.Range(1, 5);
foreach (var item in numbers)
{
Console.WriteLine(item);//12345
}
//Repeat 生成一个重复项的序列
var numbers =
Enumerable.Repeat(“Beijing 2008”, 2);
foreach (var item in numbers)
{
Console.WriteLine(item);//Beijing 2008Beijing 2008
}
生成类查询方法小结
使用生成类查询方法时,需要注意以下几点:
和其他几类方法不同,Range/Repeat 不是扩展方法,而是普通的静态方法
Range 只能产生整数序列
Repeat 可以产生泛型序列
所有的查询方法都存放在 System.Linq.Enumerable 静态类中