XML数据,或是远程的对象,它都采用同样的访问方式。
是一系列技术,包括LINQ、DLINQ、XLINQ等。其中LINQ到对象是对内存进行操作,LINQ到SQL是对数据库的操作,LINQ到XML是对XML数据进行操作。
技术采用类似于SQL语句的语法,它的语法结构是从from开始,结束于select或group子句。开头的from子句可以跟随0个或者更多个from或where子句。每个from子句都是一个产生器,它引入了一个迭代变量在序列上搜索:每个where子句是一个过滤器,它从结果中排除一些项。最后的select或group子句指定了依据迭代变量得出结果的外形。Select或group子句前面可有一个orderby子句,它指明返回结果的顺序。最后into子句可以通过把一条查询语句的结果作为产生器插入子序列查询中的方式来拼接查询。
LINQ查询
提供一种跨各种数据源和数据格式的一致模型。在LINQ查询中,始终会用到对象。可以使用相同的基本编码模式来查询和转换XML文档、SQL数据库、ADO.NET数据集、.NET集合中的数据以及对其有LINQ提供程序可用的任何其他格式的数据。
的查询操作通常由以下三个不同的操作组成:
1.获得数据源。
2.创建查询。
3.执行查询。
LINQ查询
Default.aspx,页面的Page_Load事件中的代码如下:
1 protected void Page_Load(object sender, EventArgs e)
2 {
3 string[] name = { "王楠", "汪亚旗", "刘远", "陈子胥", "苏城", "汪徐" };
4 var result = from str in name
5 where str.Length == 3
6 select str;
7 foreach (var str1 in result)
8 {
9 Response.Write(str1);
10 }
11 }
View Code
在LINQ中,查询的执行与查询本身截然不同,如果只是创建查询变量,则不会检索出任何数据。
在LINQ查询中,数据源必须支持泛型IEnumerable(T)接口,在上面的查询中由于数据源是数组,它隐式支持泛型接口,因此可以使用LINQ查询。
对于支持IEnumerable(T)或派生接口的类型则称为可查询类型。可查询类型不需要进行修改或特殊处理就可以用于LINQ数据源。如果数据源还没有作为可查询类型出现在内存中,则LINQ提供程序必须以此方式表示数据源。
例如:LINQ to XML将XML文档加载到可查询的XElement类型中:
1 XElement xelement = XElement.Load(@"G:\file1.xml");
View Code
在LINQ查询中,首先手动或使用对象关系设计器在设计时创建对象关系映射。针对这些对象编写查询,然后由LINQ to SQL在运行时处理与数据库的通信。
LINQ数据源是支持泛型IEnumerable(T)接口或从该接口继承的接口的任意对象。
查询用来指定要从数据库中检索的信息,查询还可以指定在返回这些信息之前如何对其进行排序、分组和结构化。查询存储在查询变量中,并用查询表达式进行初始化。
查询变量本身支持存储查询命令,而只有执行查询才能获取数据信息。查询分为以下两种:
1.延迟查询。在定义完查询变量后,实际的查询执行会延迟到在foreach语句中循环访问查询变量时发生。
2.强制立即执行。对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。Count、Max、Average和First就属于此类查询。由于查询本身必须使用foreach以便返回结果,因此这些查询在执行时不使用foreach语句。此外,这些类型的查询返回单个值,而不是IEnumerable集合。
LINQ查询操作
1.获取数据源
LINQ查询中,查询表达式必须以from子句开头。它同时指定了数据源和范围变量。在对源序列进行遍历的过程中,范围变量表示源序列中的每个后续元素。将根据数据源中元素的类型对范围变量进行强类型化。
Student为数据源,Stu为选择范围,代码如下:
1 var result = from Stu in Student select Stu;
View Code
2.筛选
true的元素。使用where子句生成结果。实际上,筛选器指定从源序列中排除哪些元素。
Student为数据源,Stu为选择范围,代码如下:
1 var result = from Stu in Student
2 where Stu.Address=="南阳"
3 select Stu;
View Code
&&”、“||”等。
Student为数据源,Stu为选择范围,代码如下:
1 var result = from Stu in Student
2 where Stu.Address == "南阳" && Stu.Sex == "女"
3 select Stu;
View Code
3.排序
orderby子句可以很方便地对返回的数据进行排序。orderby子句对返回的序列中的元素,根据指定的排序类型,使用默认比较器进行排序。其中,ascending表示按顺序排列,为默认方式;descending表示按逆序排列。若要把筛选的数据进行逆序排列,需要在查询语句中加上descending修饰符。
代码如下:
1 var result = from Stu in Student
2 where Stu.Address == "南阳"
3 orderby Stu.Name ascending
4 select Stu;
View Code
分组
group子句可产生按照指定的键进行分组的序列。键可以采用任何数据类型。
代码如下:
1 var result = from Stu in Student
2 group Stu by Stu.Sex;
3 foreach (var result1 in result)
4 {
5 Console.WriteLine(result1.Key);
6 foreach (Student student in result1)
7 {
8 Console.WriteLine("{0}", student.Name);
9 }
10 }
View Code
group子句结束查询时,结果采用列表形式列出。列表中的每个元素都是一个具有Key成员及根据该键分组的元素列表的对象。在循环访问生成组序列的查询时,必须使用嵌套的foreach循环。外部循环用于循环访问每个组,内部循环用于循环访问每个组的成员。
into关键字来创建可进一步查询的标识符。
1 ` var result = from Stu in Student
2 group Stu by Stu.Address into stuGroup
3 where stuGroup.Count() > 1
4 orderby stuGroup.Key
5 select stuGroup;
View Code
联接
LINQ中,不必像在SQL中那样频繁使用join,因为LINQ中的外键在对象模型中表示为包含项集合的属性。不必执行联接,只需使用点表示法访问。
6.投影
子句生成查询结果并指定每个返回的元素的类型。当select子句生成源元素副本以外的内容时,该操作称为“投影”。使用投影转换数据是LINQ查询表达式的一种强大功能。
使用LINQ进行数据转换
不仅可以用于检索数据,而且还是一个功能强大的数据转换工具。通过LINQ查询,可以将源序列用作输入,并采用多种方式修改它以创建新输出的序列。可以通过排序和分组来修改序列本身,而不必修改元素本身。但是,LINQ查询最强大的功能可能在于它能够创建新类型,这一功能在select子句中实现。例如,可执行以下任务:
1.将多个输入序列合并到具有新类型的单个输出序列中。
2.创建其元素只包含源序列中的各个元素的一个或几个属性的输出序列。
3.创建其元素包含对源数据执行的操作结果的输出序列。
4.创建不同格式的输出序列。
将多个输入联接到一个输出序列
Default.aspx,Default.aspx.cs中的代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7 using System.Xml.Linq;
8
9 namespace WebApplication1
10 {
11 public partial class Default : System.Web.UI.Page
12 {
13 protected void Page_Load(object sender, EventArgs e)
14 {
15 List<Student> students = new List<Student>()
16 {
17 new Student {First="张",
18 Last="三",
19 ID=111,
20 Street="复兴大道338",
21 City="杭州",
22 Scores=new List<int>{84,97,68,92}},
23 new Student {First="张",
24 Last="影",
25 ID=111,
26 Street="复兴大道338",
27 City="云南",
28 Scores=new List<int>{84,97,68,92}},
29 new Student {First="张",
30 Last="雨",
31 ID=111,
32 Street="复兴大道338",
33 City="芜湖",
34 Scores=new List<int>{84,97,68,92}},
35 };
36
37 List<Teacher> teachers = new List<Teacher>()
38 {
39 new Teacher {First="张",
40 Last="敏",
41 ID=111,
42 City="杭州"},
43 new Teacher {First="张",
44 Last="雪",
45 ID=111,
46 City="云南"},
47 new Teacher {First="张",
48 Last="青",
49 ID=111,
50 City="芜湖"}
51 };
52
53 //创建查询
54 var peopleInSeattle = (from student in students
55 where student.City == "芜湖"
56 select student.First + student.Last)
57 .Concat(from teacher in teachers
58 where teacher.City == "芜湖"
59 select teacher.First + teacher.Last);
60 Response.Write("在芜湖的教师和学生:");
61 //执行查询
62 foreach (var person in peopleInSeattle)
63 {
64 Response.Write(" " + person);
65 }
66 }
67
68 class Student//学生类
69 {
70 public string First { set; get; }
71 public string Last { set; get; }
72 public int ID { set; get; }
73 public string Street { set; get; }
74 public string City { set; get; }
75 public List<int> Scores;
76 }
77
78 class Teacher//教师类
79 {
80 public string First { set; get; }
81 public string Last { set; get; }
82 public int ID { set; get; }
83 public string City { set; get; }
84 }
85
86 }
87 }
View Code
将内存中的对象转换为XML
Default.aspx,Default.aspx.cs中的代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7 using System.Xml.Linq;
8
9 namespace WebApplication2
10 {
11 public partial class Default : System.Web.UI.Page
12 {
13 protected void Page_Load(object sender, EventArgs e)
14 {
15 List<Student> students = new List<Student>()
16 {
17 new Student {First="张",
18 Last="三",
19 ID=111,
20 Street="复兴大道338",
21 City="杭州",
22 Scores=new List<int>{84,97,68,92}},
23 new Student {First="张",
24 Last="影",
25 ID=111,
26 Street="复兴大道338",
27 City="云南",
28 Scores=new List<int>{84,97,68,92}},
29 new Student {First="张",
30 Last="雨",
31 ID=111,
32 Street="复兴大道338",
33 City="芜湖",
34 Scores=new List<int>{84,97,68,92}},
35 };
36
37 //创建查询
38 var studentsToXml = new XElement("Root",
39 from student in students
40 let x = String.Format("{0},{1},{2},{3}", student.Scores[0], student.Scores[1], student.Scores[2], student.Scores[3])
41 select new XElement("student",
42 new XElement("First", student.First),
43 new XElement("Last", student.Last),
44 new XElement("Scores", x)
45 )
46 );
47 //执行查询
48 Response.Write(studentsToXml);
49 }
50
51 class Student//学生类
52 {
53 public string First { set; get; }
54 public string Last { set; get; }
55 public int ID { set; get; }
56 public string Street { set; get; }
57 public string City { set; get; }
58 public List<int> Scores;
59 }
60
61 }
62 }
View Code
LINQ到ADO.NET
到ADO.NET是ADO.NET和LINQ结合的产物。LINQ到ADO.NET主要用来操作关系数据的,包括:
到DataSet:可以将更丰富的查询功能建立到DataSet中。
到SQL:提供运行时基础结构,用于将关系数据库作为对象管理。
到实体:通过实体数据模型,把关系数据在.NET环境中公开为对象,这将使得对象层成为实现LINQ支持的理想目标。
LINQ to SQL
LINQ到SQL,可以使用LINQ技术像访问内存中的集合一样访问SQL数据库。LINQ到SQL可以完成的常用功能包括选择、插入、更新、删除。这四大功能正是对应于数据库程序开发的所有执行功能,因此,在掌握了LINQ技术后,就不再需要针对特殊的数据库学习特别的SQL语法。
创建对象模型
对象模型是关系数据库在编程语言中表示的数据模型,对对象模型的操作就是对关系数据库的操作。
创建对象模型方法有三种:
使用对象关系设计器,对象关系设计器提供了用于从现有数据库创建对象模型的丰富用户界面,它包含在VS2010之中,最适合小型或中型数据库。
使用SQLMetal代码生成工具,这个工具适合大型数据库的开发,因此对于普通读者来说,这种方法就不常用了。
直接编写创建对象的代码。
使用对象关系设计器创建对象模型
O/R设计器)提供了一个可视化设计界面,用于创建基于数据库中对象的LINQ到SQL实体类和关联(关系)。它生成一个强类型的DataContext上下文对象,用于在实体类与数据库之间发送和接收数据。
DataContext上下文对象对应于类DataContext,它表示LINQ到SQL框架的主入口点,充当SQLServer数据库与映射到数据库的LINQ到SQL实体类之间管道。
DataContext 类包含用于连接数据库以及操作数据库数据的连接字符串信息和方法。
类提供的属性如下表所示:
:返回调用SubmitChanges时导致并发生冲突的集合。
:增大查询的超时期限,如果不增大则会在默认超时期限间出现超时。
:返回由使用的连接。
:指定是否延迟加载一对多关系或一对一关系。
:获取或设置与此DataContext关联的DataLoadOptions。
:指定要写入SQL查询或命令的目标。
:指定映射所基于的MetaModel。
:指示框架跟踪此DataContext的原始值和对象标识。
:为.NET框架设置要用于访问数据库的本地事物。
类提供的方法如下:
:在服务器上创建数据库。
(TResult):基础结构,执行与指定的CLR方法相关联的表值数据库函数。
:确定是否可以打开关联数据库。
:删除关联数据库。
:直接对数据库执行SQL命令。
:在删除重写方法中调用,以向LINQ到SQL重新委托生成和执行删除操作的动态SQL的任务。
:在插入重写方法中调用,以向LINQ到SQL重新委托生成和执行插入操作的动态SQL的任务。
:在更新重写方法中调用,以向LINQ到SQL重新委托生成和执行更新操作的动态SQL的任务。
:基础结构,执行数据库存储过程或指定的CLR方法关联的标量函数。
:已重载,直接对数据库执行SQL查询。
:提供对由DataContext跟踪的已修改对象的访问。
:提供有关由LINQ到SQL生成的SQL命令的信息。
:已重载,返回表对象的集合。
:已重载,使用数据库中数据刷新对象状态。
:已重载,计算要插入、更新或删除的已修改对象的集合,并执行相应命令以实现对数据库的更改。
:已重载,将现有IDataReader转换为对象。
LINQ查询数据库
到SQL中的查询与LINQ中的查询使用相同的语法,只不过它们操作的对象有所差异,LINQ到SQL查询中引用的是对象映射到数据库中的元素。
LINQ到SQL API来请求查询执行,LINQ到SQL提供程序随后会将查询转换成SQL文本,并委托ADO提供程序执行。ADO提供程序将查询结果作为DataReader返回,而LINQ到SQL提供程序将ADO结果转换成用户对象的IQueryable集合。
将信息作为只读信息进行检索
WebForm1.aspx,WebForm1.aspx.cs中的代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7
8 namespace WebApplication3
9 {
10 public partial class WebForm1 : System.Web.UI.Page
11 {
12 protected void Page_Load(object sender, EventArgs e)
13 {
14 DataClasses1DataContext data = new DataClasses1DataContext();
15 data.ObjectTrackingEnabled = false;
16 var result = from Student in data.Student select Student;
17 this.GridView1.DataSource = result;
18 this.GridView1.DataBind();
19 }
20 }
21 }
View Code
LINQ更改数据库
LINQ到SQL中执行插入、更新和删除操作的方法是:向对象模型中添加对象、更改和移除对象模型中的对象,然后LINQ到SQL会把所做的操作转化成SQL,最后把这些SQL提交到数据库执行。在默认情况下,LINQ到SQL就会自动生成动态SQL来实现插入、读取、更新和操作。
插入操作
代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7
8 namespace WebApplication3
9 {
10 public partial class WebForm1 : System.Web.UI.Page
11 {
12 protected void Page_Load(object sender, EventArgs e)
13 {
14 DataClasses1DataContext data = new DataClasses1DataContext();
15 Student student1 = new Student();
16 student1.stuNo = "1010";
17 student1.Class = "15中药五班";
18 student1.stuName = "吴语";
19 student1.Age = 23;
20 data.Student.InsertOnSubmit(student1);
21 data.SubmitChanges();
22 var result = from Student in data.Student select Student;
23 this.GridView1.DataSource = result;
24 this.GridView1.DataBind();
25 }
26 }
27 }
View Code
更新操作
代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7
8 namespace WebApplication3
9 {
10 public partial class WebForm1 : System.Web.UI.Page
11 {
12 protected void Page_Load(object sender, EventArgs e)
13 {
14 DataClasses1DataContext data = new DataClasses1DataContext();
15 var result = from Student in data.Student
16 where Student.stuNo=="1010"
17 select Student;
18 foreach (Student stu in result)
19 {
20 stu.stuName = "吴锋";
21 stu.Age = 22;
22 }
23 data.SubmitChanges();
24 this.GridView1.DataSource = result;
25 this.GridView1.DataBind();
26 }
27 }
28 }
View Code
删除操作
代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7
8 namespace WebApplication3
9 {
10 public partial class WebForm1 : System.Web.UI.Page
11 {
12 protected void Page_Load(object sender, EventArgs e)
13 {
14 DataClasses1DataContext data = new DataClasses1DataContext();
15 var result = from Student in data.Student
16 where Student.stuNo=="1012"
17 select Student;
18 foreach (Student stu in result)
19 {
20 data.Student.DeleteOnSubmit(stu);
21 }
22 data.SubmitChanges();
23 }
24 }
25 }
View Code
其实,无论对对象做了多少更改,都只是更改内存中的副本,并未对数据库中实际数据做任何更改,只有直接对DataContext显示调用SubmitChanges,所做的更改才会有效果。
DataContext会设法将所做的更改转化为等效的SQL命令,可以使用自定义的逻辑来重写这些操作,但提交的顺序是由DataContext的一项称为更改处理器的服务来协调的,事件的顺序如下:
SubmitChanges时,LINQ到SQL会检查已知对象的集合,以确定新实例是否已附加到它们。如果已附加,这些新实例将添加到被跟踪对象的集合。
2.所有具有挂起更改的对象将按照它们之间的依赖关系排序成一个对象序列。如果一个对象的更改依赖于其他对象,则这个对象将排在其依赖项之后。
LINQ到SQL会启动一个事务来封装由各条命令组成的系列。
SQL命令,然后发送到服务器。
DataContext仍具有所有更改的完整记录,因此可设法修正问题并重新调用SubmitChanges。
LinqDataSource控件
控件,为用户提供了一种将数据控件连接到多种数据源的方法,其中包括数据库数据、数据源类和内存中集合。
LinqDataSource控件,可以针对所有这些类型的数据源指定类似于数据库检索的任务(选择、筛选、分组和排序)。可以指定针对数据库表的修改任务(更新、删除和插入)。
LinqDataSource控件中的数据,可将数据绑定控件绑定到LinqDataSource控件。将数据绑定控件的DataSourceID属性设置为LinqDataSource控件的ID即可。
LinqDataSource控件中的数据。它还提供用于对数据进行排序和分页的界面。在启用数据修改后,数据绑定控件会提供用于更新、插入和删除记录的界面。
LinqDataSource控件会检索所有属性,但数据绑定控件仅显示指定的属性。
LinqDataSource控件
Default.aspx中添加如下代码:
1 <div>
2 <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="stuNo" DataSourceID="LinqDataSource1" >
3 <Columns>
4 <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
5 <asp:BoundField DataField="stuNo" HeaderText="stuNo" ReadOnly="True" SortExpression="stuNo" />
6 <asp:BoundField DataField="Class" HeaderText="Class" SortExpression="Class" />
7 <asp:BoundField DataField="stuName" HeaderText="stuName" SortExpression="stuName" />
8 <asp:BoundField DataField="Age" HeaderText="Age" SortExpression="Age" />
9 </Columns>
10 </asp:GridView>
11 <asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="WebApplication3.DataClasses1DataContext" EnableDelete="True" EnableInsert="True" EnableUpdate="True" EntityTypeName="" TableName="Student">
12 </asp:LinqDataSource>
13 </div>
View Code
QueryExtender
控件是为了简化LinqDatasource控件或EntityDataSource控件返回的数据过滤而设计的,它主要是将过滤数据的逻辑从数据控件中分离出来。
控件的使用非常简单,只需要往页面上增加一个QueryExtender控件,指定其数据源是哪个控件并设置过滤条件就可以了。比如,当在页面中显示产品的信息时,你可以使用该控件去显示那些在某个价格范围内的产品,也可以搜索用户指定名称的产品。
控件使用筛选器从数据源中检索数据,并且在数据源中不使用显式的where子句。利用该控件,能够通过声明性语法从数据源中筛选出数据。
使用QueryExtender控件有以下优点:
where子句相比,可以提供功能更丰富的筛选表达式。
LinqDataSource和EntityDataSource控件均可使用的查询语言。
LinqDataSource或EntityDataSource控件配合使用或与第三方数据源配合使用。
4.支持多种可单独和共同使用的筛选选项。
控件支持多种可用于筛选数据的选项。该控件支持搜索字符串、搜索指定范围内的值、将表中的属性值与指定的值进行比较、排序和自定义查询。在 QueryExtender 控件中以LINQ 表达式的形式提供这些选项。QueryExtender控件还支持ASP.NET动态数据专用的表达式。
控件的筛选选项如下:
:表示控件的主类。
:为数据源指定用户定义的表达式。自定义表达式可以位于函数中,并且可以从页面标记中调用。
:将排序表达式应用于IQueryable数据源对象。
:根据WhereParameters集合中的指定参数创建where子句。
:确定值大于还是小于指定的值,或者值是否在两个指定的值之间。
:搜索一个或多个字段中的字符串值,并将这些值与指定的字符串值进行比较。
:应用OrderByExpression表达式后将排序表达式应用于IQueryable数据源对象。
:使用指定的筛选器控件生成数据库查询。
:使用在源数据绑定控件中选择的数据键生成数据库查询。
QueryExtender控件实现指定字符串的筛选查询
Default.aspx中添加如下代码:
1 <div>
2 <asp:TextBox ID="TextBox1" runat="server" />
3 <asp:Button ID="Button1" runat="server" Text="查询" />
4 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="stuNo" DataSourceID="LinqDataSource1" >
5 <Columns>
6 <asp:BoundField DataField="stuNo" HeaderText="stuNo" ReadOnly="True" SortExpression="stuNo" />
7 <asp:BoundField DataField="Class" HeaderText="Class" SortExpression="Class" />
8 <asp:BoundField DataField="stuName" HeaderText="stuName" SortExpression="stuName" />
9 <asp:BoundField DataField="Age" HeaderText="Age" SortExpression="Age" />
10 </Columns>
11 </asp:GridView>
12 <asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="WebApplication3.DataClasses1DataContext" EntityTypeName="" TableName="Student">
13 </asp:LinqDataSource>
14 <asp:QueryExtender ID="QueryExtender1" runat="server" TargetControlID="LinqDataSource1">
15 <asp:SearchExpression DataFields="stuName" SearchType="StartsWith">
16 <asp:ControlParameter ControlID="TextBox1" />
17 </asp:SearchExpression>
18 </asp:QueryExtender>
19 </div>