LINQ,语言级集成查是Language INtegrated Query的意思,它是连接对象领域和数据领域的一座桥梁。可以通过C#,对各种数据源进行Linq查询:
sql数据库(LinqToSql),xml文档(LinqToXml),ado.net的数据集,以及支持IEnumerable或IEnumerable<T>接口的任意对象集合。
Linq查询一般分三个步骤进行:得到数据源——建立查询——执行查询。下面详细介绍查询。这些查询结合LinqPad来测试,关于LinqPad介绍请见:
http://www.cnblogs.com/jams742003/archive/2010/05/05/1728124.html
(一)基本查询
基本查询包括,得到数据源,查询条件,分组,排序,投影。
(1)通过字符串来演示
在LinqPad上在statements模式下进行以下测试:
string [] strTemps = strTemp.Split( new char [] { ' ' , ' , ' , ' ! ' });
var query = from st in strTemps
where st.Contains( ' a ' )
orderby st.Length descending
select st;
query.Dump();
可以得到结果:
|
What |
a |
说明:
·数据源strTemps
·定义变量st
·条件,where,用来查找单词中含有字母a的单词
·结果排序,按单词长度降序
·投影,把单词添充到结果query
现在通过匿名类型对投影进行设置:将单词和单词的长度做为结果进行填充
string [] strTemps = strTemp.Split( new char [] { ' ' , ' , ' , ' ! ' });
var query = from st in strTemps
where st.Contains( ' a ' )
orderby st.Length descending
select new { 含有字母a的单词 = st, 单词的长度 = st.Length };
query.Dump();
结果:
|
|
含有字母a的单词
|
单词的长度
|
What |
4 |
a |
1 |
上边两种都是以语句方式进行的查询,也可以以方法方式进行查询:
string [] strTemps = strTemp.Split( new char [] { ' ' , ' , ' , ' ! ' });
var query = strTemps
.Where(st => st.Contains( ' a ' ))
.OrderBy(st => st.Length)
.Select(st => st);
query.Dump();
结果同上,
string [] strTemps = strTemp.Split( new char [] { ' ' , ' , ' , ' ! ' });
var query = strTemps
.Where(st => st.Contains( ' a ' ))
.OrderBy(st => st.Length)
.Select(st => new {含有字母a的单词 = st, 单词的长度 = st.Length});
query.Dump();
通过方法进行查询时需要Lambda表达式,关于Lambda请见:
http://www.cnblogs.com/jams742003/archive/2009/12/23/1630737.html
其中的方法指的是扩展方法
下面,实现分组,为了演示分组功能,现在通过数据库来实现。
|
||
Unid
|
Name
|
Version
|
2 |
宋江 |
5 |
38 |
张青 |
1 |
40 |
张清 |
1 |
41 |
武ww |
0 |
这张表是数据,现在以Version来分组:
group c by c.Version into selfGroup
where selfGroup.Count() > 1
select selfGroup
查询以Version进行分组,且通过into selfGroup来对分组进行后续筛选,选择组内成员数在大于1的,结果是:
|
||||||||||||||||||||||||||||||||
|
以下通过数据功能来介绍查询方法
(二)排序
方法OrderByDescending,OrderBy,ThenBy,ThenByDescending
降序排列
var q = ii
.OrderByDescending(p => p)
.Select(p => p);
q.Dump();
结果:
|
90 |
55 |
25 |
12 |
1 |
(三)结果集操作
·Distinct:去重
·Except:返回一集合中存在,另一集合不存在的结果
·Intersect:交集
·Union:并集
string str2 = " abc456 " ;
// Distinct
var q1 = str1.Distinct();
q1.Dump();
a |
b |
c |
1 |
2 |
3 |
var q2 = str1.Except(str2);
q2.Dump();
1 |
2 |
3 |
var q3 = str1.Intersect(str2);
q3.Dump();
a |
b |
c |
var q4 = str1.Union(str2);
q4.Dump();
a |
b |
c |
1 |
2 |
3 |
4 |
5 |
6 |
(四)限定符
Any,All,Contains
Any用于判断是否存在元素
All 用于判断数据源中的元素是否全部满足条件
Contains用于判断数据源是否包含指定的元素
Console.WriteLine( " 是否含有元素:{0} " ,
str.Any() == true ? " 是 " : " 否 " );
Console.WriteLine( " 是否全是字母:{0} " ,
str.All(p => Char.IsLetter(p)) == true ? " 是 " : " 否 " );
Console.WriteLine( " 是否包含He:{0} " ,
str.Contains( " He " ));
(五)数据分区
Skip,SkipWhile,Take,TakeWhile
Take:取前n个
Skip:跳过前n个
TakeWhile:返回满足条件的
SkipWhile:跳过满足条件的,返回剩余的
// 得到前5个
var q1 = str.Take( 5 );
q1.Dump();
// 得到数据直到数字大于6
var q2 = (from p in str
select p).TakeWhile(p => Convert.ToInt32(p.ToString()) < 6 );
q2.Dump();
var q22 = str.TakeWhile(p => Convert.ToInt32(p.ToString()) < 6 );
q22.Dump();
// 跳过前5个
var q3 = str.Skip( 5 );
q3.Dump();
// 大于6的跳过
var q4 = str.SkipWhile(p => Convert.ToInt32(p.ToString()) < 6 );
q4.Dump();
结果略。
(六)生成新值序列
DefaultIfEmpty,Empty,Range,Repeat
DefaultIfEmpty:返回序列,如果序列为空,则返回集合中元素的默认值。例如,如果是整型数组,如果为空,那会返回整型的默认值:0;如果是对象数组,那会返回:null
var q1 = numbers.DefaultIfEmpty();
q1.Dump();
List < Customer > list = new List < Customer > ();
var q3 = list.DefaultIfEmpty();
q3.Dump();
结果:
|
0 |
|
null |
后边几个找不到。
(七)元素操作
First,Last,FirstOrDefault,LastOrDefault,ElementAt,ElementAtOrDefault,Single,SingleOrDefault
可以从字面上理解意思,每种都有两种类型,例如First和FirstOrDefault,用于返回第一个元素,如果第一个元素超出索引,则返回元素类型的默认值。
int _first = ii.First();
Console.WriteLine(_first);
int _last = ii.Last();
Console.WriteLine(_last);
int _top2 = ii.ElementAt( 1 );
Console.WriteLine(_top2);
int _top6 = ii.ElementAtOrDefault( 5 );
Console.WriteLine(_top6);
结果:
1
36
21
0
其中第4个0,是索引处不存在元素,所以返回元素类型的默认值,即整型的默认值:0
(八)数据转换
AsEnumberable:返回IEnumeralbe<T>类型
AsQueryable:将IEnumerable<T>转化为IQueryable
Cast:强制转换
ToArray:转换为数组(还有一个作用就是强制执行查询,因为查询是懒惰的(延迟))
ToList:转换为List<T>,另一个作用同上
var q = ii.ToList();
foreach ( int i in q)
Console.Write(i + " " );
(九)聚合
聚合类方法包括数量,平均数,和值,最大最小值等。
Average,Count,LongCount,Max,Min,Sum
int k = ii.Sum(p => p);
Console.Write(k);
结束之前推导一下Lambda,Func<T>,Sum扩展方法:
计算这个集合的和值
Console.WriteLine(sum1);
其中Sum方法的参数部分是一个Func<T,TResult>参数,这个参数是一个委托类型,关于Func<T>请见:
http://www.cnblogs.com/jams742003/archive/2009/10/31/1593393.html
Func<T,TResult>,表示一个T类型的参数,且返回Tresult类型的一个方法委托。现在由Func委托来实现:
int sum2 = ii.Sum(fun);
Console.WriteLine(sum2);
接下来以匿名方法来实现:
{
return i;
};
int sum3 = ii.Sum(funn);
Console.WriteLine(sum3);
然后通过明确方法来实现:
int sum4 = ii.Sum(funnn);
Console.WriteLine(sum4);
static int SelfSum( int i)
{
return i;
}