全部博文(10)
分类:
2008-10-08 16:11:15
1 LinQ初体验:
1.1 Aaa
int[] numbers
= new int[] { 6, 4, 3, 2, 9, 1, 7, 8, 5 };
var even =
numbers
.Where(p => p % 2 == 0)
.Select(p => p)
.OrderByDescending(p => p);
2 Lambda 表达式
ProcessString
p = input => input.ToLower();
foreach
(string name in foxRiver8)
{
Console.WriteLine( p ( name ) ) ;
}
在C#里,一个lambda表达式在句法上是写成一个参数列表,随后是 => 符号,随后是表达式在调用时要运算的表达式或者语句块:
params => expression
所以,当我们编写这样的lambda表达式时:
p => p.LastName ==
"Guthrie"
我们是想表示,我们在定义的Lambda接受一个参数p,要运行的代码表达式返回p.LastName的值是否等于“Guthrie”。 我们将参数命名为p是不相干的,我也可以很容易地将其命名为o,x,foo,或者我想要的任何名字。
不象匿名方法要求参数类型是明确地指明的,Lambda表达式允许省略参数类型,而允许它们根据用法来推断出类型。譬如,当我编写 p=>p.LastName == "Guthrie" 这个lambda表达式时,编译器推断出p参数属于Person类型,因为当前的Where扩展方法的对象是个范型的List< Person>集合。
Lambda参数的类型可以在编译时和被Visual Studio的intellisense引擎推断出来,这意味着在编写lambda时你将获得完全的intellisense 和编译时检查。譬如,注意当我在下面健入 p. 时,Visual Studio Orcas是如何提供intellisense完成的,因为它知道 p 是 Person类型:
注: 假如你要给一个Lambda表达式明确地声明参数的类型的话,你可以在Lambda参数表里的参数名字前声明参数类型,象这样:
3 Lambda表达式初步
3.1 A
delegate string ProcessStr(string input);
protected void Page_Load(object sender, EventArgs e)
{
var foxRiver = new string[] {
"Mike", "Smith", "Tom", "Jack" };
ProcessStr p = input => input.ToLower();
foreach (string name in foxRiver)
{
Response.Write(p(name));
}
3.2 B
List
string val1 = foxRiver.Find(i => i.IndexOf("J")==0);
Response.Write(val1);
3.3 Select和Where的用法
List
var foxs=foxRiver.Where(p => p.StartsWith("M")).Select(p => p.ToLower());
foreach (var a in foxs)
{
Response.Write(a+" ");
}
3.4 C
delegate string ProcessStr(string input);
protected void Page_Load(object sender, EventArgs e)
{
List
new Person{
Name="Mike", Age=23, Address=new Address{ Country="
new Person{ Name="Jack",
Age=30, Address=new Address{ Country="
new Person{ Name="Rose",
Age=25, Address=new Address{ Country="
new Person{ Name="Tome",
Age=24, Address=new Address{ Country="
new Person{ Name="Andy",
Age=23, Address=new Address{ Country="
new Person{ Name="Mark",
Age=28, Address=new Address{ Country="
new Person{ Name="Smith",
Age=20, Address=new Address{ Country="
new Person{ Name="Medy",
Age=30, Address=new Address{ Country="
var newPs = from p in lst group p by p.Address.Country into newP select newP;
foreach (var p in newPs)
{
Response.Write(p.First().Address.Country+" "+p.Average(p1
=> p1.Age)+"
");
}
3.5
4
int[] scores = new int[] { 2, 5, 8, 3, 6, 1, 9 };
var event1=scores.Where(p => p % 2 == 0).Select(p => p).OrderByDescending(p => p);
foreach (int a in event1)
{
Response.Write(a.ToString());
}
5 B
string[] cities = { "London", "Amsterdam", "San Francisco", "Las Vegas","Boston", "Raleigh", "Chicago",
"
GridView1.DataSource = from city in cities where city.Length > 4 orderby city select city.ToUpper();
GridView1.DataBind();
6 搜索一个数组的字符串并没多大意思,虽然有时候很有用。如果我们能对自己的功能更丰富的那些集合中搜索将 会更有趣。好消息是,LINQ使这些变得很简单。例如,为了更好记录我去过的地方,我在我的工程中建立了一 个叫"Location"的简单类:
List
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="Nice", Distance=5428, Country="
new Location { City="
};
GridView1.DataSource = from location in cities
where location.Distance > 1000
orderby location.Country, location.City
select location;
GridView1.DataBind();
7 稍微重构一下City集合
因为我们将在好几个示例中重用这个城市集合,我决定把它封装到一个"TravelOrganizer"类中
public class TravelOrganizer
{
public List
{
get
{
List
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="
new Location {
City="Nice", Distance=5428, Country="
new Location {
City="
};
}
}
}
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
where location.Distance > 1000
orderby location.Country, location.City
select location;
GridView1.DataBind();
8 使用.NET的标准查询操作符做Skip和Take操 作
LINQ支持许多内置的标准查询操作。如果你在类之前加入"using System.Query"语句你就可以在代码 中使用这些操作。例如,如果我要列出第2远到第6远的城市,我就可以使用象下面这样的编 码:
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = (from location in travel.PlacesVisited
orderby location.Distance descending
select location).Skip(1).Take(5);
GridView1.DataBind();
9 NET的标准查询操作续
除了可以返回数据集之外,我们可以使用.NET标准查询操作来返回单个或者统计数据结果。下面的例子演示了怎 么做:
Aggregate Value
Samples
Farthest
Total Travel Distance
(outside of US):
Average Distance:
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
Location farthestCity = (from location in travel.PlacesVisited
orderby location.Distance descending
select location).First();
MaxCityNameTxt.Text = farthestCity.City;
MaxCityDistanceTxt.Text = "(" + farthestCity.Distance + " miles)";
int totalDistance = (from location in travel.PlacesVisited
where
location.Country != "
select location).Sum(loc => loc.Distance);
TotalDistanceTxt.Text = totalDistance + " miles";
double averageDistance = travel.PlacesVisited.Average(loc => loc.Distance);
AverageDistanceTxt.Text = averageDistance + " miles";
}
10 匿名类型(Anonymous Types)
LINQ 能够利用的另一个C#和VB新特性之一就是对“匿名类型”的支持。这允许你不需明确声明对象模型就能很容易地创建和使用内联的类型结构,因为类型可以通过数据的初始化推断出来。这在使用LINQ查询“自定义构形(custom shape)”数据时非常的有 用。
例如,考虑这样一个场景:你正在处理一个具有许多属性的数据库或者强类型的集合-但是你只关心其中少数的 几个字段。与创建和处理整个类型相比,仅返回你所需要的字段将会更加有用些。
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
orderby location.City
select new {
City = location.City,
Distance = location.Distance
};
GridView1.DataBind();
}
11 匿名类型续
前面的示例展示了一个使用匿名类型来自定义LINQ查询输出的基本例子。下面的示例提供了一个更复杂和更实际的场景。它把我们的城市列表转换成一个分层的结果集合──我们将使用一个匿名类型来对结果按国家分组,这个匿名类型包含了一个国家名称,一个城市详细信息的子集合和在这个国家中所有城市距离的总和,这距离之和将通过第五步中示范过的lambda表达式 来计算
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
group location by location.Country into loc
select new {
Country = loc.Key,
Cities = loc,
TotalDistance = loc.Sum(dist => dist.Distance)
};
GridView1.DataBind();
12 Distinct查询
Var ps=(from p in persons select new {Age=p.Age,Address= new {p.Address.Country}}).distinct();
LINQ to SQL 是随.NET Framework Orcas版一起发布的(对象关系映射)实现,它允许你用.NET 的类来对一个关系型数据库建模。然后你可以用LINQ对数据库进行查询,以及进行更新/插入/删除数据的操作。
LINQ to SQL完全支持事务,视图和存储过程。它还提供了一种把数据验证和业务逻辑规则结合进你的数据模型的便利方式。
使用LINQ to SQL对数据库建模:
Visual Studio Orcas版中提供了一个LINQ to SQL设计器,该设计器提供了一种简易的方式,将数据库可视化地转换为LINQ to SQL对象模型。我下一篇博客将会更深入一些来介绍怎么使用该设计器(你可以观看我一月份时录制的这个关于如何从头开始创建LINQ to SQL模型的录像)。
通过LINQ to SQL设计器,我可以方便地设计出如下所示的Northwind数据库的示例模型:
上图定义了四个实体类:Product, Category, Order 和 OrderDetail。每个类的属性都映射到数据库中相应表的字段,类实体的每个实例代表了数据表中的一行记录。
在上图中,四个实体类间的箭头代表了不同实体间的关联/关系。它们主要是根据数据库中的主键/外键关系生成的。设计器上的箭头的指向表明了该关系是一对一还是一对多的关系。基于此,强类型的属性将会被加入到实体类中。例如,上边的Category类和Product类之间有一个“一对多”的关系。这意味着Category类将有一个"Products"属性,该属性代表了在该类中所有的产品对象的集合。而Product类将会有一个 "Category"属性来指向一个Category类的实例,该Category类的实例表明了了产品所属的类别。
上图中LINQ to SQL设计器的右侧列出了与我们的数据库模型交互的存储过程。在上边的例子中,我添加了一个“GetProductsByCategory”存储过程。它有一个categoryID作为输入参数,返回一个产品实体序列作为结果集。下面的代码将展示如何调用该存储过程。
理解DataContext类
当你点击LINQ to SQL设计器上的“保存"按钮时,Visual Studio将会保存我们建立的代表了实体和数据库关系的各个类。针对加入到我们的解决方案的每一个LINQ to SQL设计器文件,同时也会生成一个自定义的DataContext类。这个DataContext类是我们从数据库中查询实体或者进行更改操作的主要渠道。生成的DataContext类将含有一些属性,对应于我们在数据库中建了模的每个数据表,以及一些方法,对应于我们添加的每个存储过程。
例如,下图就是基于我们上边设计的模型而生成的的NorthwindDataContext类:
LINQ to SQL 代码例子
用LINQ to SQL 设计器对我们的数据库建模之后,我们就可以很方便地编写代码对数据库进行操作了。下边是一些展示了常见的数据库操作的代码例子:
1) 从数据库中查询Products
下面的代码用LINQ to SQL 查询语法来获取Product对象的IEnumerable序列。注意代码是如何通过Product/Category关系来仅查出那些类别是"Beverages"的产品的:
C#:
2) 更新数据库中的一条产品记录
下面的代码示范了如何从数据库中查询出单一的一条产品记录,更新它的价格,然后将改动保存至数据库:
C#:
3) 向数据库中插入一条新的Category和两条新的Products
下面的代码示范了如何生成一个新的分类,然后生成两条和该分类相关联的产品,然后将这三条记录保存到数据库中。
注意下边,我不用手工去维护主/外键关系,取而代之的是,我只向分类对象的“Products”集合中添加了两个Product记录,然后把该 Category对象添加到DataContext的“Categories”集合中,LINQ to SQL将知道自动为我持久适当的PK/FK的关系。
C#
4) 从数据库中删除Products
下面的代码示范了如何从数据库中删除所有的玩具产品:
C#:
5) 调用存储过程
下面的代码示范了如何不使用LINQ查询语法,而是通过调用我们在上面向数据模型中添加的“GetProductsByCategory”存储过程来查询Product实体。注意,一旦我查询出了Product结果集,我可以更新/删除它们,然后再调用 db.SubmitChanges()来将这些更新提交到数据库。
C#:
6) 在服务器端分页查询Products
下面的代码示范了如何通过LINQ查询语法实现高效的服务器端数据库分页查询。通过使用下面的Skip()和Take()操作符,我们从数据库中只查询出从200行开始的10条记录:
C#:
总结
LINQ to SQL提供了一种很棒的、干净利索的方法来为你的应用程序来建立数据层。一旦你定义了数据模型,你就可以方便而且有效地对它进行查询,插入,更新和删除。
13