由于MS仅授权本人在博客园上发布Intruducing Microsoft LINQ的前两章内容,故其余部分译稿不再发布.接下来的部分将小弟将以自己的理解来继续介绍LINQ基础。
好在前三章的内容已经为我们学习LINQ打好了基础,相信我们接下来的学习也不会出现多大的障碍。
在进行本节之前,我们先进行一下准备工作:建立一个Customer类,基础部分的讲解均以此类为基础:
类定义如下:
public class Customer
{
automatic properties#region automatic properties
/**//// <summary>
/// name of the customer
/// </summary>
public string Name { get; set; }
/**//// <summary>
/// address of the customer
/// </summary>
public City Address { get; set; }
/**//// <summary>
/// the
/// </summary>
public Order[] Orders { get; set; }
#endregion
//cuz we should make sure Age is between 20 and 100,we could no longer use automatic property
/**//// <summary>
/// age of the customer
/// </summary>
private int _age;
public int Age {
get {
return _age;
}
set {
if (value >=20 && value <=100)
{
_age = value;
}
else
{
Console.WriteLine("age invalid");
Console.WriteLine("Press Enter key to continue..");
Console.Read();
// throw new Exception("age invalid");
}
}
}
}
辅助此类的还有一枚举City,定义如下:
/**//// <summary>
/// cities
/// </summary>
public enum City
{
Beijing=0,
Heze=1,
Harbin=3,
Shanghai=4,
Nanyang=5,
Kunming=6
}
万事俱备,东风开吹:
一,最基础的from...in...select
这是LINQ查询中最基本的语句,其中包括三个关键字,我们看到和SQL语句中的select * from …很像吧(只不过是顺序上反了过来),的确是类似,可是意义却相差千里,T-SQL中是用于对数据表进行查询,而LINQ的这个奠基from..in..select却是不仅仅是可以进行一种查询,可以对任何实现了IEnumerable<T>的类进行查询,很激动人心?
假如我们实例化了一个Customer数组,如下:
//init Customer array
Customer[] customers = new Customer[]{
new Customer{ Name="Xianlong", Age=21, Address= City.Heze},
new Customer{ Name="Mujie", Age=23, Address= City.Kunming},
new Customer{ Name="Baoxu", Age=25, Address= City.Nanyang},
new Customer{ Name="Yanyan", Age=23, Address= City.Heze},
new Customer{ Name="Anonymous", Age=35, Address= City.Beijing},
};
那么我们就可以对该数组进行查询:
IEnumerable<Customer> HezeCustomers =
from c in customers
select c;
from来决定查询实施的目标,该目标的类必须实现了IEnumerable<T>的接口.查询结果的类型是由select来决定的,此处我们是select c,而c在此处代表的是customers,所以此查询的返回的是customer对象集合,如果我们select c.Name,那么返回的就是所有customer的name字符串组成的集合,此时相应的IEnumerable<Customer>也应修改为IEnumerable<string>.
由于此查询没有任何的限制条件,帮结果集是将数组中的所有元素均查了出来,然后我们就可以通过遍历HezeCustomers取出其中的数据来:
foreach (var item in HezeCustomers)
{
Console.WriteLine("name=" + item.Name);
Console.WriteLine("Age=" + item.Age);
Console.WriteLine("Address=" + item.Address);
Console.WriteLine("========================================================");
}
注意到我们遍历时的var关键字了吗?这是C#3.0中新增的关键字之一(相关知识:本地类型推断),如果你不认识它的话,建议你通过阅读我前面的译文对它的身世进行了解.
此时输出结果如下
二、对查询结果进行筛选和排序
仅限于将数据查询出来还远不能满足我们的需求,那么,我们就要寻找能够满足我们需求的方法来达到我们的目的(目的很纯洁,不是不可告人哦).LINQ中的Where和OrderBy关键字正好为我们提供了这种支持.还是上面的查询为例,假使我们需要查出Address为Heze的customer,并且将结果以Age倒序排列,就像在SQL语句中那样,我们自然要想到用Where来进行过滤,以desc或者某个关键字标识排列是顺序还是倒序,ok,既然想到了这一点那就不妨一试:
IEnumerable<Customer> HezeCustomers =
from c in customers
where c.Address == City.Heze
orderby c.Age descending
select c;
遍历结果集,正是我们所需要的所有地址为”Heze”的客户记录,并且其集合中的元素是Age倒序排列,如果不加descending关键字会如何?聪明的你肯定已经知道了,当然是正序排了呗,正序排列的关键字是ascending。 如果想使用多个排序条件的话,仅再增加
我们知道在C#3.0中引入了lambda表达式(即=>)和扩展方法(extention method),既然引入了,我们就可以使用,其实在上面的查询语方式中已经使用到了,下面我们就将上面的查询表达式拆解一下。像上面的c=>c.Address== City.Heze和order by c.Age之类的表达式,其实是对它们的应用的一种,对其的详细解释,请查看我前段时间发布的译稿 .鉴于此,我们用如下的代码去实现上面的功能:
Code
Func<Customer, bool> filter = d => d.Address == City.Heze;
Func<Customer, Customer> selection = c => c;
Func<Customer, int> orderby = c => c.Age;
IEnumerable<Customer> HezeCustomers =
customers
.Where(filter)
.OrderByDescending(orderby)
.Select(selection);
三、基于基本查询的扩展思考
不知道兄弟们在学习语言的时候是什么情形,就我自己而言,习惯于在学习到一种功能之后去思考这种功能能否扩展,然后根据自己的思考去查询相关的资料。同样,在这里,我们刚才使用的是一个简单的customer对象类,使用的是最简单的字段。那么我们可不可以考虑一下对该类进行扩展,然后对扩展的类也实行同样的功能?比如我们再加一个字段Projects,该Projects为Project对象的数组,然后对再对该Projects字段进行一些相应的操作是否可以?答案是肯定的,因为凡是我们想到的功能,MS的工程师们也能想到。限于篇幅,这里就不再讲解。可以自行尝试或者查看源码中的事例。
源码下载(VS2008 正式版下运行): Source Code
未完待续