Entity Framework 4 in Action读书笔记——第一章:数据访问重载:Entity Framework(3)

上一篇我们看到了关系世界和对象世界的不同,正如你看到的,应用程序使用对象模型处理数据库数据很复杂。下一个问题是谁来处理这一复杂性。答案是如果你很疯狂的话,你可以自己解决。否则你可以采用O/RM工具,更确切地说使用Entity Framework。

什么是O/RM?

O/RM是object/relational mapping(对象/关系-映射)的首字母缩写。它使用元数据信息与数据库交互,通过这种方式,你的数据层代码不需要知道数据库的结构。O/RM的核心是映射,映射技术将关系型世界和模型世界绑定在了一起。通过映射,你可以表达一个类和它的属性是怎样和数据库中的一个或多个表关联起来的。它使用O/RM的工具引擎动态构建SQL语句,检索数据并转换成对象。同样,通过追踪对象属性的变化,可以使用映射数据更新回数据库。映射信息通常表示在一个XML文件中。

O/RM是一个复杂的软件,它将开发人员从管理与数据库交互的负担下解放出来,它处理对象和关系世界之间的碰撞,查询数据并转换成对象,跟踪对象的更新,以反映在数据库中的变化等。当你有一个工具可以帮你做的时候,你再手动编码实现功能那是很愚蠢的。

现在市场上有很多O/RM产品,免费的商业的都有。到目前为止,NHibernate功能最强大也最稳定。不过现在它的领导地位正逐渐受到新版Entity Framework的威胁。

Entity Framework是怎样进行数据访问的?

Entity Framework是一个复杂的软件。它的整体结构由一些组件组成,每一个组件都实现了具体的功能。它的主要组件如下图所示:

image

实体数据模型(The Entity Data Model)

实体数据模型是模型和数据库之间的纽带。在这里,你描述数据库和模型的结构以及如何映射它们。有关实体数据模型的伟大之处在于它将你的应用程序和底层存储分离开来。数据库和模型可以有完全不同的结构,但是它们总是由实体数据模型进行关联。

实体数据模型由三个XML文件组成,每个文件都有明确的任务。这些实体数据的映射文件总结如下图:

image

(1).概念模型

概念模型是描述模型类的地方,这个文件分成两个部分:第一部分包含了所有的实体和关系;第二部分包含了它们结构的详细描述。这个文件一个重要的特点就是可以分割成很多的文件,当你的模型变得越来越大以及Visual Studio设计器的性能越来越低时这一特点就会很有用。

(2).存储模型

存储模型是概念模型的等价物,但它描述的是数据库的组织。这个文件不仅在概念上跟之前的相似,而且它们还使用了相同的XML节点。跟概念模型不一样,存储模型不能分割到多个物理文件中。这个文件的第一部分列出了所有的表,视图,存储过程和受影响的外键,第二部分介绍了在第一个节点中列出的项,

(3).映射模型

映射文件完全不一样,它的作用不是描述任何东西,而是弥补前面两个模型的不足。映射真正神奇的地方:映射一个类到一个或多个表,映射一个表到一个或多个类,定义继承映射,为更新和对象检索映射存储过程等。这个文件中只有一个重要的节点,它关联类和表,而且可以重复多次以保证一个类可以映射到多个表,反之亦然。跟存储文件一样,这个文件也不能分割为多个文件。

对象服务(Object Services)

对象服务层负责管理实体框架的对象。实体框架主要处理数据库和对象之间的不匹配,所以对对象要进行很多任务。执行查询时,对象服务层将它转换成命令树,然后传递到底层的实体客户端。这一过程有稍微的不同,这取决于你选择的查询技术。如果使用LINQ to Entities,LINQ provider产生一个表达式树,然后在命令树中解析并转化。如果使用的是Entity SQL,对象服务解析字符串并产生另一个命令树。这一过程被称之为:查询转化。

当已经执行了对数据库的查询并且底层通过映射重组了数据,对象服务就负责使用输入结构创建对象。输入的数据以概念模型的方式而不是数据库的方式组织成行和列。这意味着每一行代表一个对象,如果它有一个属性引用其他类,那么该列就包含那个类的所有行。下图表示了数据是怎样组织的:

image

由于数据的这种组织方式,创建对象的过程相当简单,我们称这个过程为“对象的具体化”。

当对象准备使用时,上下文就派上了用场。上下文指的是应用程序和实体框架之间通信的生命周期。上下文的建立是使用一个众所周知的类(可能是ObjectContext或者 Context类),只要在代码中引用它就会起作用,或者它从来都没有被释放。上下文类从一开始就使用了,因为它创建了查询对象模型的入口。

对象具体化后就自动添加到上下文中,但是这一行为由于性能原因可能被忽略。在具体化的过程中,如果对象已经在上下文中存在,引擎就会跳过,在上下文中引用的对象就返回给正在执行查询的代码。也就是说上下文扮演了一个本地缓存的角色。

自动附加到上下文的对象会由状态管理组件进行追踪。这一机制确保了对对象的任何修改都能正确的在数据库中管理和记录。为了做到这一点,状态管理存储了每个对象加载时的初始数据以便对它们进行比较和执行优化更新。状态管理组件有很多选项可以自定义它的行为。

最后,对象服务层协调数据存储更新,查询状态管理器修改,它还控制着执行命令所需的管道代码的创建。

实体客户端数据提供程序(Entity Client data provider)

实体客户端负责与数据库进行通信,为了简化其架构,这一层并没有物理的连接到数据库,而是依赖ADO.NET数据提供程序。鉴于对象服务使用EDM的对象模型管理对象,实体客户端使用EDM的所有文件。它需要映射和存储模型的文件转换命令树到执行数据库的SQL命令,然后需要概念模型的文件转换表格结构的数据到概念型数据。

在这一点上你必须清楚地理解系统是如何处理查询,使用它们访问数据库,并将结果数据转换成对象的。在需要最大性能的特殊情况下,你可能忽略掉服务对象层直接查询这一层。性能的提高不仅是跳过了一层,而且避免了执行查询最慢的具体化过程。显而易见,LINQ to Entities不适用于直接查询实体客户端,因为LINQ操作对象,但是这一层完全不知道它们。这种情况下,Entity SQL是唯一一种能够实现直接查询实体客户端的语言。

LINQ to Entities

LINQ to Entities是LINQ的专业用语,可以对模型进行类型查询。幸亏LINQ的语法,你可以对模型进行类型查询并返回一个编译时检查的对象。

尽管LINQ to Entities操作对象,但最终翻译成SQL语句。很多LINQ的方法或重载不能在SQL中表示,例如,ElementAt方法不支持但是在语法上是有效的。对该方法的调用不会引起编译时的错误,但是在运行时会抛出NotSupportedException异常。Where方法重载的第二个参数接受一个整数不能翻译成SQL语句,这只会引起一个运行时异常。

Entity SQL

Entity SQL是查询对象模型的另一种方式。像LINQ to Entities一样,Entity SQL也是对模型进行查询,不同的是Entity SQL是基于字符串的,在某些情况下更可取。

Entity SQL使我们见过的最复杂的语言之一。Entity Framework团队在为Entity Framework创建查询语言的时为了便于开发者理解,他们选择了像SQL的语法,这也就是为什么叫Entity SQL。随着Entity SQL的发展演变,越来越多的特性被加入,查询功能的范围变宽,需要新的语言功能。目前,Entity SQL超过150种功能,并且与原来的SQL语法保持一定的兼容性。

尽管它很复杂,有些情况下Entity SQL优于INQ to Entities。首先,它是基于字符串的,在运行时可以很容易的根据条件创建查询。第二,Entity SQL是唯一可以用作底层(直接使用实体客户端)数据检索的语言。

写在最后的话

终于把第一章写完了,太多理论了,下一章将真正进入Entity Framework的世界。

posted @ 2011-08-13 17:32  BobTian  阅读(4237)  评论(2编辑  收藏  举报