现在的位置: 首页 > 综合 > 正文

LinqToObject(1)——查询

2014年02月12日 ⁄ 综合 ⁄ 共 4964字 ⁄ 字号 评论关闭

 

 
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 strTemp = "Oh,What a pity!";
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 strTemp = "Oh,What a pity!";
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 strTemp = "Oh,What a pity!";
string[] strTemps = strTemp.Split(new char[] { ' ', ',', '!' });

var query = strTemps
            .Where(st => st.Contains('a'))
            .OrderBy(st => st.Length)
            .Select(st => st);

query.Dump();

 

结果同上,

string strTemp = "Oh,What a pity!";
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来分组:

from c in Customers
group c by c.Version into selfGroup
where selfGroup.Count()>1
select selfGroup

 

查询以Version进行分组,且通过into selfGroup来对分组进行后续筛选,选择组内成员数在大于1的,结果是:

 
 
Key=
 1
 

 

 
 
Unid
 FirstName
 LastName
 CreateTime
 Address
 Version
 
38
 张
 青
 2010-1-6 9:40:47
 清河县1
 1
 
40
 张
 清
 2010-1-6 10:00:32
 未知1
 1
 
78
 
 
 
 
 2
 
 

 

以下通过数据功能来介绍查询方法

(二)排序

方法OrderByDescending,OrderBy,ThenBy,ThenByDescending

降序排列

int[] ii = new int[] { 1, 90, 12, 25, 55 };
var q=ii
    .OrderByDescending(p=>p)
    .Select(p=>p);
q.Dump();

 

结果:

 
 
90
 
55
 
25
 
12
 
1
 

 

(三)结果集操作

·Distinct:去重

·Except:返回一集合中存在,另一集合不存在的结果

·Intersect:交集

·Union:并集

 

string str1="abc123aab";
string str2="abc456";

//Distinct
var q1=str1.Distinct();
q1.Dump();

 

a
 
b
 
c
 
1
 
2
 
3
 

 

//Except
var q2=str1.Except(str2);
q2.Dump();

 

1
 
2
 
3
 

 

//Intersect
var q3=str1.Intersect(str2);
q3.Dump();

 

a
 
b
 
c
 

 

//Union
var q4=str1.Union(str2);
q4.Dump();

 

a
 
b
 
c
 
1
 
2
 
3
 
4
 
5
 
6
 

 

(四)限定符

Any,All,Contains

Any用于判断是否存在元素

All 用于判断数据源中的元素是否全部满足条件

Contains用于判断数据源是否包含指定的元素

 

string str = "Hello world!";
 

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:跳过满足条件的,返回剩余的

string str = "0123456789";

//得到前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

List<int> numbers = new List<int>();
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[] ii=new int[]{1,21,0,36};

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>,另一个作用同上

int[] ii=new int[]{1,21,0,36};

var q=ii.ToList();

foreach(int i in q)
    Console.Write(i+" ");

 

(九)聚合

聚合类方法包括数量,平均数,和值,最大最小值等。

Average,Count,LongCount,Max,Min,Sum

 

int[] ii=new int[]{1,21,0,36};

int k=ii.Sum(p=>p);
Console.Write(k);

 

结束之前推导一下Lambda,Func<T>,Sum扩展方法:

int[] ii=new int[]{1,21,0,36};
 

计算这个集合的和值

int sum1=ii.Sum(p=>p);
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委托来实现:

Func<int,int> fun=p=>p;
int sum2=ii.Sum(fun);

Console.WriteLine(sum2);

 

接下来以匿名方法来实现:

Func<int,int> funn=delegate(int i)
{
    return i;
};

int sum3=ii.Sum(funn);
Console.WriteLine(sum3);

 

然后通过明确方法来实现:

 

Func<int,int> funnn=SelfSum;

int sum4=ii.Sum(funnn);
Console.WriteLine(sum4);

static int SelfSum(int i)
{
    return i;
}

 

抱歉!评论已关闭.