《LINQ从基础到项目实战PPT第4章LINQtoSQL.ppt》由会员分享,可在线阅读,更多相关《LINQ从基础到项目实战PPT第4章LINQtoSQL.ppt(43页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第4章 LINQ to SQL本章结合实例介绍LINQ to SQL编程接口。LINQ to SQL用于操作关系型数据库中的数据,基于关系型数据库中存在的关系数据模型建立与之相对应的对象关系模型(Object Relation Model),使用LINQ to SQL对该模型的操作被转换成相应的SQL语句并在数据库中执行。简单地讲,LINQ to SQL可以使用对象操作的方式来操作关系型数据库中的数据,相比传统的基于字符串的数据库操作方式,使用LINQ to SQL更加安全方便,LINQ to SQL在对象领域和关系数据领域之间架起了一座桥梁。章节内容4.1 LINQ to SQL基础4.2
2、对象-关系映射4.3 DataContex对象4.4 标准数据库操作4.5 并发访问冲突检测与处理4.1 LINQ to SQL基础 4.1.1 ORM框架大部分ORM框架将数据库的关系模型抽象成对象模型后,对数据库的访问就只能通过对象模型以标准的对象访问方式来进行,而不能使用大多数开发人员比较熟悉的SQL语句来访问这些对象;而LINQ to SQL不同,它不仅允许以标准的对象访问方式来访问对象模型,而且可以使用非常类似于SQL语句的查询表达式来操作对象模型。4.1 LINQ to SQL基础 下面的一段代码是使用LINQ to SQL对数据库中的数据进行查询操作。BookDataContex
3、t ctx=new BookDataContext();/创建数据库通信对象var books=from p in ctx.Book where p.BOOKID=99 select p;/LINQ to SQL查询表达式4.1.2 建立实例运行数据库环境 数据库关系图4.2 对象-关系映射对象-关系映射(ORM,Object Relation Mapping)是随着面向对象的软件开发方法发展而产生的一种设计思想。面向对象的开发方法是当今企业级应用开发中的主流开发方法,关系型数据库是企业级应用中持久保存数据的主流媒介。对象和关系型数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据
4、库中则表现为关系型数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系型数据虽然无法直接表示多对多关联和继承关系,但是可以表示主从关系。借助于ORM,关系型数据和对象之间可以相互以自身熟悉的方式表示对方的关系,给程序开发带来很大的便利。对象-关系映射系统一般以中间件的形式存在,主要实现为程序对象到关系数据库数据的自动映射。4.2.1 使用内联属性实体类是一个普通的自定义类型,只是因为其特殊的用途(一般用于映射物理表)才被称为实体类。使用内联属性(Inline attribute)建立映射是指通过在实体类的定义代码中使用一些特定的属性(attribute)修饰类名或者属性(propert
5、y),来指定该类或者该属性具体映射到数据库中的表或者表的某一列的方法,下面通过一个具体的实例4-1来演示如何使用内联属性方法来建立对象-关系映射。运行Visual Studio 2008,新建一个控制台应用程序,创建完成后的【解决方案资源管理器】窗口如图所示。4.2.1 使用内联属性【解决方案资源管理器】窗口 4.2.1 使用内联属性为了在代码中使用LINQ to SQL的功能,需要向项目添加的引用。右击【解决方案资源管理器】窗口中的【引用】,在打开的右键菜单中单击【添加引用】命令,为项目添加的引用,【添加引用】窗口如图所示。4.2.1 使用内联属性 【添加引用】窗口 4.2.2 使用XML映
6、射文件一个XML映射文件由一系列的节点(Node)构成,其中根节点是一个Database元素(element),用来指定要映射的数据库信息。Database元素可以包含一个或者多个Table元素,用于指定将要映射的物理表信息,Table元素由一个Type元素和多个Column元素(或Association元素)组成。其中,Type元素用来指定实体类;Column元素用来指定列信息;Association元素用来建立主键-外键关联关系。与内联属性不同的是,这里的Column元素包含一个Member属性(attribute),用来指定映射到实体类的属性(property)名称。4.2.3 使用Sq
7、lMetal工具程序SqlMetal程序是Visual Studio 2008提供的一个命令行工具程序,用于自动化生成映射数据库中物理表的实体类定义代码。SqlMetal程序的使用语法定义如下。SqlMetal 选项 选项:/server:数据库服务器名称/database:服务器上的数据库目录/user:登录用户ID(默认值:使用Windows身份验证)/password:登录密码(默认值:使用Windows身份验证)/conn:数据库连接字符串,不能与/server、/database、/user 或/password一起使用/timeout:要在SqlMetal访问数据库时使用的超时值(
8、默认值:0,表示无限期)4.2.3 使用SqlMetal工具程序/views 提取数据库视图/functions 提取数据库函数/sprocs 提取存储过程/dbml:文件 输出为 dbml,不能与/map选项一起使用/code:文件 输出为源代码,不能与/dbml选项一起使用/map:文件 生成映射文件而不是属性,不能与/dbml选项一起使用/language:源代码语言:VB或C#(默认值:派生自代码文件名的扩展名)/namespace:生成代码的命名空间(默认值:无命名空间)/context:数据上下文类的名称(默认值:派生自数据库名称)/entitybase:生成代码中的实体类的基类(
9、默认值:实体没有基类)4.2.3 使用SqlMetal工具程序/pluralize 使用英语语言规则自动设置类和成员名称的单复数形式/serialization:生成可序列化的类:None或Unidirectional(默认值:None)/provider:提供程序类型:SQLCompact、SQL2000或SQL2005 可以是SqlExpress mdf文件、SqlCE sdf文件或dbml中间文件4.2.4 使用LINQ to SQL设计器为了可视化的创建映射数据库中物理表的实体类定义代码,Visual Studio 2008提供了另外一个程序,即LINQ to SQL设计器。LINQ
10、to SQL设计器程序允许使用拖放的方式来可视化地创建实体类定义代码,使用可视化方式创建实体类的最大好处是对创建的类模型有一个很直观的理解。4.2.4 使用LINQ to SQL设计器LINQ to SQL设计器窗口4.3 DataContex对象ataContex对象是LINQ to SQL编程接口中最重要的一个组件,专门用于处理与数据库相关的操作,包括连接数据库、监视实体类的更改并将更改向数据库提交、缓存数据等任务。可以说,只要使用LINQ to SQL,就必须使用DataContex对象。在实际应用中,一般不是直接使用DataContex类对象来完成特定的功能,而是使用一个继承DataC
11、ontex类的子类对象来实现功能,利用SqlMetal程序或者LINQ to SQL设计器自动生成的实体类代码中就自动包含一个DataContex类的子类定义。4.3.1 DataContext构造方法DataContex类的构造方法用于初始化一个DataContex对象,DataContex类具有4个构造方法原型,第一个构造方法的原型定义如下。/DataContex第一个构造方法原型DataContext(string fileOrServerOrConnection);DataContex类的第二个构造方法的原型定义如下。/DataContex第二个构造方法原型DataContext(Sy
12、stem.Data.IDbConnection connection);4.3.1 DataContext构造方法DataContex类的第三个构造方法原型定义如下。/DataContex第三个构造方法原型DataContext(string fileOrServerOrConnection,DataContex类的第四个构造方法原型定义如下。/DataContex第四个构造方法原型DataContext(System.Data.IDbConnection connection,System.Data.Linq.MappingSource mapping)4.3.2 SubmitChanges
13、方法SubmitChanges方法用于将程序中对实体类对象的更改保存至数据库中。在此方法被调用之前,DataContex对象会缓存程序中对实体类对象的更改;如果此时不调用SubmitChanges方法,这些更改信息将不会被保存到数据库中。/SubmitChanges方法第一个原型void SubmitChanges()/SubmitChanges方法第二个原型void SubmitChanges(ConflictMode failureMode)4.3.3 CreateDatabase方法CreateDatabase方法用于在数据库服务器上根据实体类映射信息或者XML映射文件创建一个数据库,其
14、方法原型定义如下。void CreateDatabase()CreateDatabase方法的使用非常简单,没有参数,只是根据映射信息创建一个包含若干物理表的数据库。4.3.4 DatabaseExists方法DatabaseExists方法用于判断DataContex对象使用的数据库是否存在,其方法原型定义如下。bool DatabaseExists()此方法的使用非常简单,没有参数,只是简单地根据DataContex的初始化数据库连接信息判断数据库是否存在。如果存在就返回true,否则返回false。下面的代码使用了此方法原型。4.3.4 DatabaseExists方法DataConte
15、xt dc=new DataContext(Data Source=localhost;Initial Catalog=LinqTestDatabase2;User ID=sa;Password=sql,);Console.WriteLine(The LinqTestDatabase2database 0.,dc.DatabaseExists()?exists:does not exist);4.3.5 DeleteDatabase方法DeleteDatabase方法用于删除DataContex对象使用的数据库,其方法原型定义如下。void DeleteDatabase()此方法使用非常简单,
16、下面的代码使用DeleteDatabase方法实现删除数据库功能。DataContext dc=new DataContext(Data Source=localhost;Initial Catalog=LinqTestDatabase2;User ID=sa;Password=sql,);dc.DeleteDatabase();/删除数据库4.3.6 ExecuteQuery方法ExecuteQuery方法用于执行一个带参数的SQL查询语句,其方法的原型定义如下。IEnumerable ExecuteQuery(string query,params object parameters)4.
17、3.7 ExecuteCommand方法ExecuteCommand方法用于执行一个带参数的SQL命令语句,包括插入、修改以及删除等操作,其方法原型定义如下。int ExecuteCommand(string command,params object parameters)此方法原型接收一个SQL命令字符串参数command和一个SQL参数数组parameters,返回操作影响的行数。4.3.8 GetTable方法GetTable方法用于获取一个关于实体类对象的序列,其方法原型定义如下。Table GetTable()此方法原型没有参数,当调用时只需要指定实体类型T的值即可。DataCon
18、tex对象使用此方法中指定的实体类类型信息查询数据库中的对应物理表,并将返回的记录信息封装成实体类对象放入一个序列中返回。4.3.9 Refresh方法Refresh方法用于根据数据库中的数据更新内存中的实体类对象的状态。在多用户并发访问数据库的情况下,此方法可以获知数据库中的最新数据。Refresh方法的原型如下。/Refresh方法第一个原型void Refresh(RefreshMode mode,object entity)/Refresh方法第二个原型void Refresh(RefreshMode mode,params object entities)/Refresh方法第三个原
19、型void Refresh(RefreshMode mode,System.Collections.IEnumerable entities)4.3.10 GetChangeSet方法GetChangeSet方法用于获取实体类对象中发生更改的集合。由于SubmitChanges方法将会根据更改的对象集合来生成相应的SQL语句发送给数据库,通过GetChangeSet方法可以获知哪些对象信息将会保存到数据库中。GetChangeSet方法的原型定义如下。/GetChangeSet方法原型ChangeSet GetChangeSet()此方法返回一个ChangeSet对象,Change Set对象
20、包含Inserts、Updates和Deletes这3个属性。4.3.11 Log属性Log属性用于输出DataContex对象与数据库通信时使用的SQL语句信息。DataContex对象负责将实体类的更改转换成SQL语句发送给数据库执行,最终发送给数据库的SQL语句内容保存在Log属性中,可以根据此属性内容进行调试、优化等工作。属性的类型为System.IO.TextWriter,在使用时只需指定一个TextWriter类型对象给Log属性,DataContex对象将信息自动发送到TextWriter对象。4.3.12 实体跟踪服务DataContex对象作为LINQ to SQL中最重要的
21、一个组件,专门用于处理与数据库相关的操作,本身提供了许多非常重要的服务功能,实体跟踪服务(Identity Tracking)就是这些服务中的一种。4.3.13 更改跟踪服务更改跟踪服务(Change Tracking)是DataContex对象提供的另外一种非常重要的服务。自从DataContex对象查询数据库生成实体类对象并在实体类对象上启动实体跟踪服务开始后,更改跟踪服务会一直跟踪实体类对象的所有更改信息,直到该实体类对象被SubmitChanges方法将更改信息保存到数据库中为止。4.4 标准数据库操作本节将介绍如何使用LINQ to SQL执行标准的数据库操作,即插入、修改、查询以及
22、删除操作等。4.4.1 IQueryable泛型接口本书第2章介绍了表达式树,表达式树可以在系统运行时动态编译成一段可执行代码,由于在运行时进行动态编译,系统可以在执行时将一组相关的表达式树优化组合一起编译,提高查询效率,实现某些特定的功能。下面的代码使用了Lambda表达式查询满足特定条件的元素。/使用Lambda表达式查询数组元素int nums=new int 6,2,7,1,9,3;IEnumerable numsLessThanFour=nums.Where(i=i i);4.4.2 插入操作插入操作(Inserts)在LINQ to SQL中非常简单,首先实例化一个实体类对象;然后
23、将该实体类对象添加到一个类型为Table的集合中,或者添加到一个类型为EntitySet的集合中,这里的类型T为该实体类;最后,调用DataContex对象的SubmitChanges方法保存插入结果。4.4.3 查询操作LINQ to SQL中的查询(Queries)语句与LINQ to OBJECT中的查询语句用法非常相似,但是在底层实现上差别很大。首先,LINQ to SQL中的查询返回结果类型为IQueryable,而不是IEnumerable,这主要是为了利用表达式树功能。例如,下面的LINQ to SQL查询代码返回的结果类型为IQueryable。4.4.3 查询操作/使用LIN
24、Q to SQL查询数据库string sql=Data Source=localhost;Initial Catalog=LinqTestDatabase;User ID=sa;Password=sql;DataContext dc=new DataContext(sql);/Table类型也是继承于IQueryable类型Table tbl=dc.GetTable();/查询表达式的返回结果类型为IQueryableIQueryable books=from book in tbl where book.Price 30 select book;4.4.4 更新操作LINQ to SQL中
25、的更新操作(Updates)非常简单,首先修改实体类对象的属性,其次调用DataContex对象的SubmitChanges方法,最后(有必要的话)进行并发冲突检测处理。4.4.5 删除操作在LINQ to SQL中,删除操作(Deletes)意味着将一个或者多个实体类对象从一个类型为Table的集合中删除。Table集合类型本身提供了相应的方法(DeleteOnSubmit方法等)来完成删除操作,最后,需要调用DataContex对象的SubmitChanges方法保存删除结果。4.5 并发访问冲突检测与处理在多用户并发访问数据库的情况下,当一个用户从数据库中读取数据并修改数据,最后试图将修
26、改保存到数据库中的这段时间内,恰巧另外一个用户也读取并修改相同的数据,且早于第一个用户向数据库提交了更改,这时如果第一个用户向数据库提交更改就会发生并发冲突(Concurrency Conflicts)。在多用户访问数据库的环境中,并发访问冲突一般比较常见。当并发冲突发生时,程序应该提供一定的机制对冲突进行检测与处理。4.5.1 乐观并发乐观并发(Optimistic Concurrency)是一种比较常见的处理并发的方式,它对于并发冲突的发生持有一种乐观的态度,认为在大部分的程序运行时间内,不会发生并发冲突。因此,程序在修改数据库中的数据时,不会锁定所修改的数据,而是采用一种在修改时动态检测
27、并发冲突是否发生的处理方式。乐观并发可以允许大量的用户访问数据库,是目前应用最广泛的一种并发冲突处理方式。LINQ to SQL自动提供了对乐观并发的支持,提供了很多有用的方法来帮助完成冲突检测和冲突处理等任务。4.5.1 乐观并发LINQ to SQL提供了两种方法可以用来检测并发冲突,第一种使用IsVersion属性(attribute)来修饰实体类的列属性(property)。如果实体类某一列属性使用IsVersion修饰并且其值为true,则此列将被LINQ to SQL用于检测并发冲突。4.5.2 悲观并发悲观并发(Pessimistic Concurrency)对于并发冲突的发生持有一种悲观的态度,认为在大部分的程序运行时间内,都可能发生并发冲突。因此,程序在修改数据库中的数据时,将锁定所修改的数据,直到修改完成才解除锁定。悲观并发不会发生并发冲突,当数据库的用户数量比较少的情况下,悲观并发可以很好地满足需求。使用悲观并发来避免并发冲突的发生非常简单,只需要将数据操作的代码包装在一个事务中即可。