【原文地点】Using LINQ with ASP.NET (Part 1)
【原文颁发日期】Sunday, May 14, 2006 9:49 PM
最近使我感动不已的新鲜事之一就是LINQ系列技能的呈现,包罗LINQ,DLINQ,XLINQ和不久后的其他技能。
LINQ将被完全集成到代号为Orcas的下个版本Visual Studio中,并且它也包括了一些很是酷的框架和 东西支持,包罗完全的智能感知和可视化设计器支持。你可以在这儿下载上周宣布的LINQ五月份CTP版。这个CTP版 本的亮点就是它能在VS 2005上运行,使你可以或许当即开始深入研究LINQ。它实现了许多用户的反馈(例 如:在DLINQ中添加了对存储进程的支持),而且包括了一个内置的ASP.NET网站项目模板来辅佐你在ASP.NET 中利用它(留意:你也可以在VS 2005 Web Application Project 中利用LINQ)。
我将在接下来的几周中颁发一系列文章来先容奈何在ASP.NET工程 中利用LINQ/DLINQ/XLINQ。下面这第一个走过场的示范将辅佐你相识一些LINQ重要的根基观念。你可以下 载LINQ五月份CTP版,然后跟着文章的举办慢慢输入相应代码(在下面我会列出所有代码),可能你也可以 在这儿下载并运行我所做示例的 完整.zip文件(留意:你仍然需要下载LINQ五月份版来运行.zip文件中的示 例)。
留意:C#和VB都完全支持LINQ,DLINQ和XLINQ。在下面的示例中 我将利用C#。
第0步:成立一个C# LINQ ASP.NET网站
成立一个能利用LINQ/DLINQ/XLINQ和新的C#3.0语言特性的ASP.NET网站,在VS中选择文件->新建网站然后选 择"LINQ ASP.NET Web Site Template":(注:VS2008中不需要这样的模板页面)
默认会建设一个如下所示的网站 工程:
留意它在/bin文件夹中引入了一些LINQ措施集。它同样在web.config文件中添加了一些设置以汇报VS和ASP.NET 利用C# 3.0编译器来编译和运行措施:
<system.codedom>
<compilers>
<compilerlanguage="c#;cs;csharp"
& nbsp; extension=".cs"
type="Microsoft.CSharp.CSharp3CodeProvider, CSharp3CodeDomProvider"/>
</compilers>
</system.codedom>
留意C# 3.0编译器和CodeDOM提供器可以和C# 2.0版本并肩运行, 因此你无需担忧安装LINQ会粉碎VS或ASP.NET。
第一步:成立第一个利用了LINQ的ASP.NET页 面
新建一个叫Step1.aspx的新页面。添加一个GridView控件到页面中,如下所 示:
<%@ Page Language="C#" CodeFile="Step1.aspx.cs" Inherits="Step1" %>
<html>
<body>
<form id="form1" runat="server">
<div>
<h1>City Names</h1>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</div>
</form>
</body>
</html>
然后在靠山代码文件中我们将编写经典的“hello world”LINQ示例-包罗对一列字符串的搜索和排 序:
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Query;
public partial class Step1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string[] cities = { "London", "Amsterdam", "San Francisco", "Las Vegas",
& nbsp; "Boston", "Raleigh", "Chicago", "Charlestown",
& nbsp; "Helsinki", "Nice", "Dublin" };
GridView1.DataSource = from city in cities
& nbsp; where city.Length > 4
& nbsp; orderby city
& nbsp; select city.ToUpper();
GridView1.DataBind();
}
}
在上面的示例中,我列出了一组我本年一月到五月所去过的都市的名称。然后我用LINQ查询表达式(query expression)对这个数组举办操纵。这个查询表达式返回名字多于4个字符的所有都市,然后凭据都市名 称的字母举办排序并把名字转换为大写。
LINQ查询返回如下范例:IEnumerable<T>-"select"子句选择的工具范例抉择了这里 的<T>的范例。因为上面例子中"city"是一个字符串,所以范例安详的功效是一个如下所示的基于泛型 的荟萃:
IEnumerable<string> result = from city in cities
& nbsp; where city.Length > 4
& nbsp; orderby city
& nbsp; select city.ToUpper();
因为ASP.NET控件能绑定到任何的IEnumerable荟萃,所以我们可以很容易的把LINQ查询功效绑定到GridView中, 然后挪用DataBind()要领来生成如下的页面输出:
留意,除了可以利用上面的GridView控件外,我也可以利用 <asp:repeater>, <asp:datalist>, <asp:dropdownlist>, 可能任何其他ASP.NET的列表 控件(可以是产物自带可能开拓人员本身开拓的控件)。在这些示例中我只利用了<asp:gridview>-但 是你们可以利用任何其他的控件。
第二步:利用成果更富厚的荟萃
搜索一个数组的字符串并没多大意思,固然有时候很有用。假如我们能对本身的成果更富厚的那些荟萃中搜索将 会更有趣。好动静是,LINQ使这些变得很简朴。譬喻,为了更好记录我去过的处所,我在我的工程中成立了一 个叫"Location"的简朴类:
using System;
public class Location
{
// Fields
private string _country;
private int _distance;
private string _city;
// Properties
public string Country
{
get { return _country; }
set { _country = value; }
}
public int Distance
{
get { return _distance; }
set { _distance = value; }
}
public string City
{
get { return _city; }
set { _city = value; }
}
}
它果真了三个属性来暗示国度、都市名称和到西雅图的间隔。然后我新建一个包括GridView控件的Step3.aspx页 面,个中GridView界说了三列,如下所示:
<%@ Page Language="C#" CodeFile="Step2.aspx.cs" Inherits="Step2" %>
<html>
<body>
<form id="form1" runat="server">
<h1>Cities and their Distances</h1>
<asp:GridView ID="GridView1" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:BoundField HeaderText="Country" DataField="Country" />
<asp:BoundField HeaderText="City" DataField="City" />
<asp:BoundField HeaderText="Distance from Seattle" DataField="Distance" />
</Columns>
</asp:GridView>
</form>
</body>
</html>
然后我成立一个Location工具荟萃来绑定到Grid中,靠山代码文件如下所示:
using System;
using System.Collections.Generic;
using System.Web;
using System.Query;
public partial class Step2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<Location> cities = new List<Location>{
& nbsp; & nbsp; new Location { City="London", Distance=4789, Country="UK" },
& nbsp; & nbsp; new Location { City="Amsterdam", Distance=4869, Country="Netherlands" },
& nbsp; & nbsp; new Location { City="San Francisco", Distance=684, Country="USA" },
& nbsp; new Location { City="Las Vegas", Distance=872, Country="USA" },
& nbsp; & nbsp; new Location { City="Boston", Distance=2488, Country="USA" },
& nbsp; & nbsp; new Location { City="Raleigh", Distance=2363, Country="USA" },
& nbsp; & nbsp; new Location { City="Chicago", Distance=1733, Country="USA" },
& nbsp; & nbsp; new Location { City="Charleston", Distance=2421, Country="USA" },
& nbsp; & nbsp; new Location { City="Helsinki", Distance=4771, Country="Finland" },
& nbsp; & nbsp; new Location { City="Nice", Distance=5428, Country="France" },
& nbsp; & nbsp; new Location { City="Dublin", Distance=4527, Country="Ireland" }
& nbsp; };
GridView1.DataSource = from location in cities
& nbsp; where location.Distance > 1000
& nbsp; orderby location.Country, location.City
& nbsp; select location;
GridView1.DataBind();
}
}
上面的靠山代码展示了几个很是酷的特性。首先是C# 3.0新的轻便的结构器写法,在建设工具的同时,还可以同 时配置这些工具的属性的值::
new Location { City="London", Distance=4789, Country="UK" }
这在实例化和同时添加工具到荟萃中的景象下很是有用,以及在 后头将用到的匿名范例的景象中也很是有用。留意到我这次并没有用数组,而是用了一个范例为Location的基 于泛型的List荟萃。LINQ支持对任何的IEnumerable<T>荟萃执行查询,所以你可以利用现有的任何泛型 可能非泛型的工具荟萃。
在下面的LINQ查询中我返回了间隔西雅图高出100英里的都市的荟萃。我还选择了对查询举办先国度后都市名称 的排序操纵。这个LINQ查询的功效的范例是由location变量来确定下来的─在这里,其范例 是Location:
IEumerable<Location> result = from location in cities
& nbsp; where location.Distance > 1000
& nbsp; orderby location.Country, location.City
& nbsp; select location;
当我把功效绑定到GridView中将会获得如下功效:
第三步:稍微重构一下City荟萃
因为我们将在好几个示例中重用这个都市荟萃,我抉择把它封装到一个"TravelOrganizer"类中,如下所 示:
using System;
using System.Collections.Generic;
public class TravelOrganizer
{
public List<Location> PlacesVisited
{
get
{
List<Location> cities = new List<Location>{
& nbsp; & nbsp; new Location { City="London", Distance=4789, Country="UK" },
& nbsp; & nbsp; new Location { City="Amsterdam", Distance=4869, Country="Netherlands" },
& nbsp; & nbsp; new Location { City="San Francisco", Distance=684, Country="USA" },
& nbsp; & nbsp; new Location { City="Las Vegas", Distance=872, Country="USA" },
& nbsp; & nbsp; new Location { City="Boston", Distance=2488, Country="USA" },
& nbsp; & nbsp; new Location { City="Raleigh", Distance=2363, Country="USA" },
& nbsp; & nbsp; new Location { City="Chicago", Distance=1733, Country="USA" },
& nbsp; & nbsp; new Location { City="Charleston", Distance=2421, Country="USA" },
& nbsp; & nbsp; new Location { City="Helsinki", Distance=4771, Country="Finland" },
& nbsp; new Location { City="Nice", Distance=5428, Country="France" },
& nbsp; & nbsp; new Location { City="Dublin", Distance=4527, Country="Ireland" }
& nbsp; & nbsp; };
return cities;
}
}
}
这使我只需要编写如下的代码就能获得跟上面同样的功效:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Query;
public partial class Step3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
& nbsp; where location.Distance > 1000
& nbsp; orderby location.Country, location.City
& nbsp; select location;
GridView1.DataBind();
}
}
LINQ很酷之处就是它是强范例的。这意味着,
1) 你的所有的查询城市举办编译时查抄。不像此刻的SQL语句,你只有到运行时才会发明你的错误所 在。这意味着你在开拓时就可以查抄你的代码的正确性,譬喻,假如我把上面的"distance"误写成 了"distanse",编译器将为我捕捉到这个错误。
2) 当你写LINQ查询的时候你将在VS或免费的Visual Web Developer中得到智能感知的提示。这不只加 快了编码的输入速度,并且使我们在处理惩罚无论简朴照旧巨大的荟萃和数据源工具模子时都变得很是容 易。
第四步:利用.NET的尺度查询操纵符做Skip和Take操 作
LINQ支持很多内置的尺度查询操纵。假如你在类之前插手"using System.Query"语句你就可以在代码 中利用这些操纵。譬喻,假如我要列出第2远到第6远的都市,我就可以利用象下面这样的编 码:
using System;
using System.Web.UI;
using System.Query;
public partial class Step4 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = (from location in travel.PlacesVisited
& nbsp; orderby location.Distance descending
& nbsp; select location).Skip(1).Take(5);
GridView1.DataBind();
}
}
留意我是怎么通过间隔的远迩来对功效举办排序的。然后我使 用Skip操纵来跳过第一个都市,然后利用Take操纵来只返回5个结 果。
NET尺度查询操纵的真正强大之处在于,这些操纵不是写死 的(hard-coded ),任何开拓人员都可以添加新的或替换个中的操纵。这就可以支持实现很是强有力的特定 域(domain specific)操纵。譬喻,当你在DLINQ里利用Skip和Take操纵时,DLINQ实际上是把这些操纵转换成 处事器端分页的靠山SQL逻辑,这样,只有少量的记录从数据库返回,不管数据表中是否有十几万条数据。这 意味着我们可以在大量干系数据之上很等闲地实现高效的web数据分页。留意:在LINQ正式刊行之前,你可以 利用这里提到的技能。
第五步:.NET的尺度查询操纵续
除了可以返回数据集之外,我们可以利用.NET尺度查询操纵来返回单个可能统计数据功效。下面的例子演示了怎 么做:
<%@ Page Language="C#" CodeFile="Step5.aspx.cs" Inherits="Step5" %>
<html>
<body>
<form id="form1" runat="server">
<div>
<h1>Aggregate Value Samples</h1>
<div>
<b>Farthest Distance City:</b>
<asp:Label ID="MaxCityNameTxt" runat="server" Text="Label"></asp:Label>
<asp:Label ID="MaxCityDistanceTxt" runat="server" Text="Label"></asp:Label>
</div>
<div>
<b>Total Travel Distance (outside of US):</b>
<asp:Label ID="TotalDistanceTxt" runat="server" Text="Label"></asp:Label>
</div>
<div>
<b>Average Distance:</b>
<asp:Label ID="AverageDistanceTxt" runat="server" Text="Label"></asp:Label>
</div>
</div>
</form>
</body>
</html>
Step5.aspx.cs靠山代码文件:
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Query;
public partial class Step5 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
//
// Calculate farthest city away
Location farthestCity = (from location in travel.PlacesVisited
& nbsp; & nbsp; orderby location.Distance descending
& nbsp; & nbsp; select location).First();
MaxCityNameTxt.Text = farthestCity.City;
MaxCityDistanceTxt.Text = "(" + farthestCity.Distance + " miles)";
//
// Calculate total city distances of all cities outside US
int totalDistance = (from location in travel.PlacesVisited
& nbsp; where location.Country != "USA"
& nbsp; select location).Sum(loc => loc.Distance);
TotalDistanceTxt.Text = totalDistance + " miles";
//
// Calculate average city distances of each city trip
double averageDistance = travel.PlacesVisited.Average(loc => loc.Distance);
AverageDistanceTxt.Text = averageDistance + " miles";
}
}
留意,上面最后两个例子利用了新的Lambda表达式(Lambda Expression)支持-这些表达式答允我们通过譬如象 委托这样的代码段在数据之上做进一步的操纵,从而计较出一个功效来。你也可以用之来成立你本身的.NET查 询操纵(譬喻:你可以成立一些特定规模的查询来计较运费可能收入税)。所有的工具都是强范例的,并且支 持智能感知和编译时查抄。
上面示例的输出如下所示:
第六步:匿名范例(Anonymous Types)
LINQ可以或许操作的另一个C#和VB新特性之一就是对“匿名范例”的支 持。这答允你不需明晰声明工具模子就能很容易地建设和利用内联的范例布局,因为范例可以通过数据的初始 化揣度出来。这在利用LINQ查询“自界说构形(custom shape)”数据时很是的有 用。
譬喻,思量这样一个场景:你正在处理惩罚一个具有很多属性的数据库可能强范例的荟萃-可是你只体贴个中少数的 几个字段。与建设和处理惩罚整个范例对比,仅返回你所需要的字段将会越发有用些。我们来新建一 个"step6.aspx"文件来实现以上操纵:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Step6.aspx.cs" Inherits="Step6" %>
<html>
<body>
<form id="form1" runat="server">
<div>
<h1>Anonymous Type</h1>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</div>
</form>
</body>
</html>
在我们的靠山代码文件中我们将编写一个利用匿名范例的LINQ查询,如下所 示:
using System;
using System.Web.UI;
using System.Query;
public partial class Step6 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
& nbsp; orderby location.City
& nbsp; select new {
& nbsp; & nbsp; City = location.City,
& nbsp; & nbsp; Distance = location.Distance
& nbsp; };
GridView1.DataBind();
}
}
留意,我们并没有像上面一样从select子句中返回一个"location"工具,我们通过新建一个具有City和Distance 两个属性的匿名范例来实现。这两个属性的范例是按照它们初始化时赋与的值来自动确定的,在这里是一个是 string,另一个是int。将其绑定到GridView时,将发生如下输出:
第七步:匿名范例续
前面的示例展示了一个利用匿名范例来自定 义LINQ查询输出的根基例子。下面的示例提供了一个更巨大和更实际的场景。它把我们的都市列表转换成一个分层的功效荟萃──我们将利用一个匿名范例来对功效按国度分组,这个匿名范例包括了一个国度名称,一个城 市具体信息的子荟萃和在这个国度中所有都市间隔的总和,这间隔之和将通过第五步中示范过的lambda表达式 来计较:
using System;
using System.Web.UI;
using System.Query;
public partial class Step7 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
& nbsp; group location by location.Country into loc
& nbsp; select new {
& nbsp; & nbsp; Country = loc.Key,
& nbsp; & nbsp; Cities = loc,
& nbsp; & nbsp; TotalDistance = loc.Sum(dist => dist.Distance)
& nbsp; };
GridView1.DataBind();
}
}
我们.aspx页面中的GridView是这样界说的:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Step7.aspx.cs" Inherits="Step7" %>
<html>
<body>
<form id="form1" runat="server">
<div>
<h1>Groupings with Anonymous Classes</h1>
<asp:GridView ID="GridView1" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:BoundField HeaderText="Country" DataField="Country" />
<asp:TemplateField HeaderText="Cities">
& nbsp; <ItemTemplate>
& nbsp;
& nbsp; <asp:BulletedList ID="BulletedList1" runat="server"
& nbsp; & nbsp; DataSource='<%#Eval("Cities")%>' DataValueField="City"/>
& nbsp;
& nbsp; </ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Total Distance" DataField="TotalDistance" />
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
留意,我在GridView的模版列中添加了一个"Cities"列,而且在个中添加了一个<asp:bulletedlist>控件 (一个新的ASP.NET 2.0自带控件)来绑定在上面用LINQ查询所获得的分层功效。生成的输出如下所 示:
留意,所有上面的绑定语法和条理绑定在此刻的ASP.NET 2.0中是完全支持的,所以,你可以在现有的措施中使 用这些技能。新颖(我也认为很是酷)之处,是匿名范例和LINQ提供的数据构形成果,这个成果使得在ASP.NET 控件里绑定分层数据很是容易。
下一步
上面所有的例子操纵的都是当地内存中的荟萃数据。他们展示了你如安在.NET工具模子中利用LINQ,包罗那些你 本身建设的范例。
在我未来的有关LINQ的文章中,我将深入接头LINQ,操作新的DLINQ支持利用上面提到的技能来处理惩罚干系数据库 ,和通过新的XLINQ支持来处理惩罚XML文件和布局。LINQ项目标长处在于,在所有的应用中,其句法和观念都是一 样的,这样,你一旦学会利用LINQ对一个数组或荟萃做查询,你也就知道了在处理惩罚数据库甚至XML文件时所需 的所有观念。
譬喻,如果你利用DLINQ生成了Northwinds数据库中供给商(Suppliers)和产物( Products)表相对应的.NET范例 (注:你不需要编写任何代码就可以实现),那么要获取分层的数据功效,而且将其绑定到GridView上,你只 要写下面这个编码就可以了(留意:我们利用了跟前面的例子一样的数据构形技能,只从数据库中取得两列数 据,而且自动地把每个供给商和其对应的产物组合成一个条理布局的结 果):
using System;
using System.Query;
public partial class Data_Data2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Northwind db = new Northwind();
GridView1.DataSource = from x in db.Suppliers
& nbsp; where x.Country == "USA"
& nbsp; orderby x.Country
& nbsp; select new {
& nbsp; & nbsp; x.CompanyName,
& nbsp; & nbsp; x.Country,
& nbsp; & nbsp; x.Products
& nbsp; };
GridView1.DataBind();
}
}
不需要特另外SQL语句和代码──这些就是实现高效获取和组装条理数据所需的所有代码(留意:只取出了需要的 列和行的数据-DLINQ可以利用LINQ的长途函数支持因而我们没须要耐久化可能取出所有数据库表可能一行中 的所有列)。并且这些都是范例安详的,同样具有完全的编译时查抄,智能感知和调试支 持。
更棒的是,接入一个新的LINQ提供器(DLINQ和XLINQ是两例)的机制是完全果真的──因此那些已经成立可能利用现 有数据提供措施(譬喻:O/R数据库映射)的开拓人员可以很容易的无缝地把他们的实现和LINQ整合起来。一 旦你相识了LINQ,你就知道了开拓LINQ所需的所有的根基常识。
总结
本文对一些即将到来的很是酷的技能做了一个较量大致的概述。你可以从这儿下载LINQ五月份CTP版来实验一下。你也可以 在这儿下载并运行我在上面所建 示例的.zip文件。
希 望本文对你有所辅佐,
Scott
标签: ASP.NET, Visual Studio, .NET, LINQ, Data