问题描述
最近使我激动不已的新鲜事之一就是LINQ系列技术的出现,包括LINQ,DLINQ,XLINQ和不久后的其他技术。LINQ将被完全集成到代号为Orcas的下个版本VisualStudio中,而且它也包含了一些非常酷的框架和工具支持,包括完全的智能感知和可视化设计器支持。你可以在这儿下载上周发布的LINQ五月份CTP版。这个CTP版本的亮点就是它能在VS2005上运行,使你能够立即开始深入研究LINQ。它实现了很多用户的反馈(例如:在DLINQ中添加了对存储过程的支持),并且包含了一个内置的ASP.NET网站项目模板来帮助你在ASP.NET中使用它(注意:你也可以在VS2005WebApplicationProject中使用LINQ)。我将在接下来的几周中发表一系列文章来介绍怎样在ASP.NET工程中使用LINQ/DLINQ/XLINQ。下面这第一个走过场的示范将帮助你了解一些LINQ重要的基本概念。你可以下载LINQ五月份CTP版,然后随着文章的进行逐步输入相应代码(在下面我会列出所有代码),或者你也可以在这儿下载并运行我所做示例的完整.zip文件(注意:你仍然需要下载LINQ五月份版来运行.zip文件中的示例)。注意:C#和VB都完全支持LINQ,DLINQ和XLINQ。在下面的示例中我将使用C#。第0步:建立一个C#LINQASP.NET网站建立一个能使用LINQ/DLINQ/XLINQ和新的C#3.0语言特性的ASP.NET网站,在VS中选择文件->新建网站然后选择"LINQASP.NETWebSiteTemplate":默认会创建一个如下所示的网站工程:注意它在bin文件夹中引入了一些LINQ程序集。它同样在web.config文件中添加了一些配置以告诉VS和ASP.NET使用C#3.0编译器来编译和运行程序:<system.codedom><compilers><compilerlanguage="c#;cs;csharp" 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控件到页面中,如下所示:<%@PageLanguage="C#"CodeFile="Step1.aspx.cs"Inherits="Step1"%><html><body><formid="form1"runat="server"><div><h1>CityNames</h1><asp:GridViewID="GridView1"runat="server"></asp:GridView></div></form></body></html>然后在后台代码文件中我们将编写经典的“helloworld”LINQ示例-包括对一列字符串的搜索和排序:usingSystem;usingSystem.Web;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Query;publicpartialclassStep1:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){string[]cities={"London","Amsterdam","SanFrancisco","LasVegas", "Boston","Raleigh","Chicago","Charlestown", "Helsinki","Nice","Dublin"};GridView1.DataSource=fromcityincities wherecity.Length>4 orderbycity selectcity.ToUpper();GridView1.DataBind();}}在上面的示例中,我列出了一组我今年一月到五月所去过的城市的名称。然后我用LINQ查询表达式(queryexpression)对这个数组进行操作。这个查询表达式返回名字多于4个字符的所有城市,然后按照城市名称的字母进行排序并把名字转换为大写。LINQ查询返回如下类型:IEnumerable<T>-"select"子句选择的对象类型决定了这里的<T>的类型。因为上面例子中"city"是一个字符串,所以类型安全的结果是一个如下所示的基于泛型的集合:IEnumerable<string>result=fromcityincities wherecity.Length>4 orderbycity selectcity.ToUpper();因为ASP.NET控件能绑定到任何的IEnumerable集合,所以我们可以很容易的把LINQ查询结果绑定到GridView中,然后调用DataBind()方法来生成如下的页面输出:注意,除了可以使用上面的GridView控件外,我也可以使用<asp:repeater>,<asp:datalist>,<asp:dropdownlist>,或者任何其他ASP.NET的列表控件(可以是产品自带或者开发人员自己开发的控件)。在这些示例中我只使用了<asp:gridview>-但是你们可以使用任何其他的控件。第二步:使用功能更丰富的集合搜索一个数组的字符串并没多大意思,虽然有时候很有用。如果我们能对自己的功能更丰富的那些集合中搜索将会更有趣。好消息是,LINQ使这些变得很简单。例如,为了更好记录我去过的地方,我在我的工程中建立了一个叫"Location"的简单类:usingSystem;publicclassLocation{//Fieldsprivatestring_country;privateint_distance;privatestring_city;//PropertiespublicstringCountry{get{return_country;}set{_country=value;}}publicintDistance{get{return_distance;}set{_distance=value;}}publicstringCity{get{return_city;}set{_city=value;}}}它公开了三个属性来表示国家、城市名称和到西雅图的距离。然后我新建一个包含GridView控件的Step3.aspx页面,其中GridView定义了三列,如下所示:
解决方案
解决方案二:
<%@PageLanguage="C#"CodeFile="Step2.aspx.cs"Inherits="Step2"%><html><body><formid="form1"runat="server"><h1>CitiesandtheirDistances</h1><asp:GridViewID="GridView1"AutoGenerateColumns="false"runat="server"><Columns><asp:BoundFieldHeaderText="Country"DataField="Country"/><asp:BoundFieldHeaderText="City"DataField="City"/><asp:BoundFieldHeaderText="DistancefromSeattle"DataField="Distance"/></Columns></asp:GridView></form></body></html>然后我建立一个Location对象集合来绑定到Grid中,后台代码文件如下所示:usingSystem;usingSystem.Collections.Generic;usingSystem.Web;usingSystem.Query;publicpartialclassStep2:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){List<Location>cities=newList<Location>{ newLocation{City="London",Distance=4789,Country="UK"}, newLocation{City="Amsterdam",Distance=4869,Country="Netherlands"}, newLocation{City="SanFrancisco",Distance=684,Country="USA"}, newLocation{City="LasVegas",Distance=872,Country="USA"}, newLocation{City="Boston",Distance=2488,Country="USA"}, newLocation{City="Raleigh",Distance=2363,Country="USA"}, newLocation{City="Chicago",Distance=1733,Country="USA"}, newLocation{City="Charleston",Distance=2421,Country="USA"}, newLocation{City="Helsinki",Distance=4771,Country="Finland"}, newLocation{City="Nice",Distance=5428,Country="France"}, newLocation{City="Dublin",Distance=4527,Country="Ireland"} };GridView1.DataSource=fromlocationincities wherelocation.Distance>1000 orderbylocation.Country,location.City selectlocation;GridView1.DataBind();}}上面的后台代码展示了几个非常酷的特性。首先是C#3.0新的简便的构造器写法,在创建对象的同时,还可以同时设置这些对象的属性的值::newLocation{City="London",Distance=4789,Country="UK"}这在实例化和同时添加对象到集合中的情形下非常有用,以及在后面将用到的匿名类型的情形中也非常有用。注意到我这次并没有用数组,而是用了一个类型为Location的基于泛型的List集合。LINQ支持对任何的IEnumerable<T>集合执行查询,所以你可以使用现有的任何泛型或者非泛型的对象集合。在下面的LINQ查询中我返回了距离西雅图超过100英里的城市的集合。我还选择了对查询进行先国家后城市名称的排序操作。这个LINQ查询的结果的类型是由location变量来确定下来的─在这里,其类型是Location:IEumerable<Location>result=fromlocationincities wherelocation.Distance>1000 orderbylocation.Country,location.City selectlocation;当我把结果绑定到GridView中将会得到如下结果:第三步:稍微重构一下City集合因为我们将在好几个示例中重用这个城市集合,我决定把它封装到一个"TravelOrganizer"类中,如下所示:usingSystem;usingSystem.Collections.Generic;publicclassTravelOrganizer{publicList<Location>PlacesVisited{get{List<Location>cities=newList<Location>{ newLocation{City="London",Distance=4789,Country="UK"}, newLocation{City="Amsterdam",Distance=4869,Country="Netherlands"}, newLocation{City="SanFrancisco",Distance=684,Country="USA"}, newLocation{City="LasVegas",Distance=872,Country="USA"}, newLocation{City="Boston",Distance=2488,Country="USA"}, newLocation{City="Raleigh",Distance=2363,Country="USA"}, newLocation{City="Chicago",Distance=1733,Country="USA"}, newLocation{City="Charleston",Distance=2421,Country="USA"}, newLocation{City="Helsinki",Distance=4771,Country="Finland"}, newLocation{City="Nice",Distance=5428,Country="France"}, newLocation{City="Dublin",Distance=4527,Country="Ireland"} };returncities;}}}这使我只需要编写如下的代码就能得到跟上面同样的结果:usingSystem;usingSystem.Collections.Generic;usingSystem.Web;usingSystem.Web.UI;usingSystem.Query;publicpartialclassStep3:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){TravelOrganizertravel=newTravelOrganizer();GridView1.DataSource=fromlocationintravel.PlacesVisited wherelocation.Distance>1000 orderbylocation.Country,location.City selectlocation;GridView1.DataBind();}}LINQ很酷之处就是它是强类型的。这意味着,1)你的所有的查询都会进行编译时检查。不像现在的SQL语句,你只有到运行时才会发现你的错误所在。这意味着你在开发时就可以检查你的代码的正确性,例如,如果我把上面的"distance"误写成了"distanse",编译器将为我捕获到这个错误。2)当你写LINQ查询的时候你将在VS或免费的VisualWebDeveloper中获得智能感知的提示。这不仅加快了编码的输入速度,而且使我们在处理无论简单还是复杂的集合和数据源对象模型时都变得非常容易。第四步:使用.NET的标准查询操作符做Skip和Take操作LINQ支持许多内置的标准查询操作。如果你在类之前加入"usingSystem.Query"语句你就可以在代码中使用这些操作。例如,如果我要列出第2远到第6远的城市,我就可以使用象下面这样的编码:usingSystem;usingSystem.Web.UI;usingSystem.Query;publicpartialclassStep4:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){TravelOrganizertravel=newTravelOrganizer();GridView1.DataSource=(fromlocationintravel.PlacesVisited orderbylocation.Distancedescending selectlocation).Skip(1).Take(5);GridView1.DataBind();}}注意我是怎么通过距离的远近来对结果进行排序的。然后我使用Skip操作来跳过第一个城市,然后使用Take操作来只返回5个结果。
解决方案三:
NET标准查询操作的真正强大之处在于,这些操作不是写死的(hard-coded),任何开发人员都可以添加新的或替换其中的操作。这就可以支持实现非常强有力的特定域(domainspecific)操作。例如,当你在DLINQ里使用Skip和Take操作时,DLINQ实际上是把这些操作转换成服务器端分页的后台SQL逻辑,这样,只有少量的记录从数据库返回,不管数据表中是否有十几万条数据。这意味着我们可以在大量关系数据之上很轻易地实现高效的web数据分页。注意:在LINQ正式发行之前,你可以使用这里提到的技术。第五步:.NET的标准查询操作续除了可以返回数据集之外,我们可以使用.NET标准查询操作来返回单个或者统计数据结果。下面的例子演示了怎么做:<%@PageLanguage="C#"CodeFile="Step5.aspx.cs"Inherits="Step5"%><html><body><formid="form1"runat="server"><div><h1>AggregateValueSamples</h1><div><b>FarthestDistanceCity:</b><asp:LabelID="MaxCityNameTxt"runat="server"Text="Label"></asp:Label><asp:LabelID="MaxCityDistanceTxt"runat="server"Text="Label"></asp:Label></div><div><b>TotalTravelDistance(outsideofUS):</b><asp:LabelID="TotalDistanceTxt"runat="server"Text="Label"></asp:Label></div><div><b>AverageDistance:</b><asp:LabelID="AverageDistanceTxt"runat="server"Text="Label"></asp:Label></div></div></form></body></html>Step5.aspx.cs后台代码文件:usingSystem;usingSystem.Collections.Generic;usingSystem.Web.UI;usingSystem.Query;publicpartialclassStep5:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){TravelOrganizertravel=newTravelOrganizer();////CalculatefarthestcityawayLocationfarthestCity=(fromlocationintravel.PlacesVisited orderbylocation.Distancedescending selectlocation).First();MaxCityNameTxt.Text=farthestCity.City;MaxCityDistanceTxt.Text="("+farthestCity.Distance+"miles)";////CalculatetotalcitydistancesofallcitiesoutsideUSinttotalDistance=(fromlocationintravel.PlacesVisited wherelocation.Country!="USA" selectlocation).Sum(loc=>loc.Distance);TotalDistanceTxt.Text=totalDistance+"miles";////CalculateaveragecitydistancesofeachcitytripdoubleaverageDistance=travel.PlacesVisited.Average(loc=>loc.Distance);AverageDistanceTxt.Text=averageDistance+"miles";}}注意,上面最后两个例子使用了新的Lambda表达式(LambdaExpression)支持-这些表达式允许我们通过譬如象委托这样的代码段在数据之上做进一步的操作,从而计算出一个结果来。你也可以用之来建立你自己的.NET查询操作(例如:你可以建立一些特定领域的查询来计算运费或者收入税)。所有的对象都是强类型的,而且支持智能感知和编译时检查。上面示例的输出如下所示:第六步:匿名类型(AnonymousTypes)LINQ能够利用的另一个C#和VB新特性之一就是对“匿名类型”的支持。这允许你不需明确声明对象模型就能很容易地创建和使用内联的类型结构,因为类型可以通过数据的初始化推断出来。这在使用LINQ查询“自定义构形(customshape)”数据时非常的有用。例如,考虑这样一个场景:你正在处理一个具有许多属性的数据库或者强类型的集合-但是你只关心其中少数的几个字段。与创建和处理整个类型相比,仅返回你所需要的字段将会更加有用些。我们来新建一个"step6.aspx"文件来实现以上操作:<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="Step6.aspx.cs"Inherits="Step6"%><html><body><formid="form1"runat="server"><div><h1>AnonymousType</h1><asp:GridViewID="GridView1"runat="server"></asp:GridView></div></form></body></html>在我们的后台代码文件中我们将编写一个使用匿名类型的LINQ查询,如下所示:usingSystem;usingSystem.Web.UI;usingSystem.Query;publicpartialclassStep6:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){TravelOrganizertravel=newTravelOrganizer();GridView1.DataSource=fromlocationintravel.PlacesVisited orderbylocation.City selectnew{ City=location.City, Distance=location.Distance };GridView1.DataBind();}}注意,我们并没有像上面一样从select子句中返回一个"location"对象,我们通过新建一个具有City和Distance两个属性的匿名类型来实现。这两个属性的类型是根据它们初始化时赋与的值来自动确定的,在这里是一个是string,另一个是int。将其绑定到GridView时,将产生如下输出:第七步:匿名类型续前面的示例展示了一个使用匿名类型来自定义LINQ查询输出的基本例子。下面的示例提供了一个更复杂和更实际的场景。它把我们的城市列表转换成一个分层的结果集合──我们将使用一个匿名类型来对结果按国家分组,这个匿名类型包含了一个国家名称,一个城市详细信息的子集合和在这个国家中所有城市距离的总和,这距离之和将通过第五步中示范过的lambda表达式来计算:usingSystem;usingSystem.Web.UI;usingSystem.Query;publicpartialclassStep7:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){TravelOrganizertravel=newTravelOrganizer();GridView1.DataSource=fromlocationintravel.PlacesVisited grouplocationbylocation.Countryintoloc selectnew{ Country=loc.Key, Cities=loc, TotalDistance=loc.Sum(dist=>dist.Distance) };GridView1.DataBind();}}我们.aspx页面中的GridView是这样定义的:<%@PageLanguage="C#"AutoEventWireup="true"CodeFile="Step7.aspx.cs"Inherits="Step7"%><html><body><formid="form1"runat="server"><div><h1>GroupingswithAnonymousClasses</h1><asp:GridViewID="GridView1"AutoGenerateColumns="false"runat="server"><Columns><asp:BoundFieldHeaderText="Country"DataField="Country"/><asp:TemplateFieldHeaderText="Cities"> <ItemTemplate> <asp:BulletedListID="BulletedList1"runat="server" DataSource='<%#Eval("Cities")%>'DataValueField="City"/> </ItemTemplate></asp:TemplateField><asp:BoundFieldHeaderText="TotalDistance"DataField="TotalDistance"/></Columns></asp:GridView></div></form></body></html>注意,我在GridView的模版列中添加了一个"Cities"列,并且在其中添加了一个<asp:bulletedlist>控件(一个新的ASP.NET2.0自带控件)来绑定在上面用LINQ查询所得到的分层结果。生成的输出如下所示:
解决方案四:
注意,所有上面的绑定语法和层次绑定在现在的ASP.NET2.0中是完全支持的,所以,你可以在现有的程序中使用这些技术。新颖(我也认为非常酷)之处,是匿名类型和LINQ提供的数据构形功能,这个功能使得在ASP.NET控件里绑定分层数据非常容易。下一步上面所有的例子操作的都是本地内存中的集合数据。他们展示了你如何在.NET对象模型中使用LINQ,包括那些你自己创建的类型。在我将来的有关LINQ的文章中,我将深入讨论LINQ,利用新的DLINQ支持使用上面提到的技术来处理关系数据库,和通过新的XLINQ支持来处理XML文件和结构。LINQ项目的好处在于,在所有的应用中,其句法和概念都是一样的,这样,你一旦学会使用LINQ对一个数组或集合做查询,你也就知道了在处理数据库甚至XML文件时所需的所有概念。例如,假如你使用DLINQ生成了Northwinds数据库中供应商(Suppliers)和产品(Products)表相对应的.NET类型(注:你不需要编写任何代码就可以实现),那么要获取分层的数据结果,并且将其绑定到GridView上,你只要写下面这个编码就可以了(注意:我们使用了跟前面的例子一样的数据构形技术,只从数据库中取得两列数据,并且自动地把每个供应商和其对应的产品组合成一个层次结构的结果):usingSystem;usingSystem.Query;publicpartialclassData_Data2:System.Web.UI.Page{protectedvoidPage_Load(objectsender,EventArgse){Northwinddb=newNorthwind();GridView1.DataSource=fromxindb.Suppliers wherex.Country=="USA" orderbyx.Country selectnew{ x.CompanyName, x.Country, x.Products };GridView1.DataBind();}}不需要额外的SQL语句和代码──这些就是实现高效获取和组装层次数据所需的所有代码(注意:只取出了需要的列和行的数据-DLINQ可以使用LINQ的远程函数支持因而我们没必要持久化或者取出所有数据库表或者一行中的所有列)。而且这些都是类型安全的,同样具有完全的编译时检查,智能感知和调试支持。更棒的是,接入一个新的LINQ提供器(DLINQ和XLINQ是两例)的机制是完全公开的──因此那些已经建立或者使用现有数据提供程序(例如:O/R数据库映射)的开发人员可以很容易的无缝地把他们的实现和LINQ整合起来。一旦你了解了LINQ,你就知道了开发LINQ所需的所有的基本知识。总结本文对一些即将到来的非常酷的技术做了一个比较粗略的概述。你可以从这儿下载LINQ五月份CTP版来尝试一下。你也可以在这儿下载并运行我在上面所建示例的.zip文件。希望本文对你有所帮助,【原文地址】UsingLINQwithASP.NET(Part1)【原文发表日期】Sunday,May14,20069:49PM转自:http://blog.joycode.com/scottgu/articles/83789.aspx
解决方案五:
good
解决方案六:
不知,帮顶
解决方案七:
关注接分
解决方案八:
关注一下...
解决方案九:
关注中......
解决方案十:
关注,学习