本章内容包括:
|
我们先从分析实体的生命周期和它的状态开始。
实体生命周期
在其生存期期间,一个实体只有一个状态。在了解如何检索状态之前,先看看什么是实体状态。实体状态就是声明为以下值的System.Data.EntityState类型的枚举:
Added——实体标记为added。
Deleted——实体标记为deleted。
Modified——实体已经被修改。
Unchanged——实体还没有被修改。
Detached——实体不能被追踪。
这些状态代表什么?状态与什么相关?实体如何从一个状态传递到另一个状态?这些状态影响数据库吗?回答这些问题,必须先看看对象生命周期背后的概念。
理解实体状态
如第三章所述,上下文(context)持有对从数据库检索的所有对象的引用。对我们的讨论更重要的是,上下文保持实体的状态并且维护对实体属性的修改。这一功能称为change tracking(或object tracking)。
如果在上下文外部创建一个实体,它的状态为Detached,因为上下文不能追踪它。
如果将一个实体附加到上下文,它的状态就变为Unchanged。如果从数据库中检索一个实体,然后从上下文中移除,实体的状态为Detached。如果检索一个实体,释放上下文,然后创建一个新的上下文,给它添加一个实体,这个实体的状态则为Added。这些例子说明,状态是实体和对它持有引用的上下文间的关系。
让我们看个例子。假设在OrderIT中有两个方法,第一个是检索关于customer的数据,第二个用于更新数据。客户使用第一个方法检索数据并在窗体中显示。在这个方法中,创建了一个上下文来检索数据,然后销毁上下文。
用户修改了一些数据,例如发货地址(shipping address),然后调用第二个方法更新修改的customer数据并保存它。在网络服务(web service)方法中,创建一个新的上下文并且将实体附加到它。新的上下文并不知道什么数据已经被修改了,除非它去数据库中比较。
去数据库中的代价比较大,所以并不会自动执行。这就是说实体附加到上下文时,它进入Unchanged状态,因为上下文对修改一无所知。如果实体状态反映数据库的实际状态,它会是Modified,但是事实并非如此。这个例子很简单,但是它解释了为什么状态是表示实体和上下文间的关系而不是实体和数据库的关系。
当然,实体的状态影响它的持久化方式。这并不奇怪,当持久化实体时,在数据库中使用INSERT, UPDATE, 或DELETE命令保存那些Added,Modified或者Deleted状态。
实体状态如何影响数据库
状态不仅仅表示上下文中的实体状态,还表示数据如何持久化到数据库。每一个状态,都有一个对应的SQL命令。
Added状态的实体使用INSERT命令在映射的表中创建一个新行进行持久化。Modified实体在表中已经有了对应的行,所以使用UPDATE命令持久化。Deleted状态的实体在表中有对应的行,但是它触发DELETE而不是UPDATE。
Detached和Unchanged状态对数据库没有影响:detached实体不能被上下文追踪,所以不用持久化,而unchanged实体没有修改的东西需要持久化。
在其生存期期间,实体可以改变其状态。
实体生命周期的状态改变
实体的状态可以由上下文(context)自动设置也可以由开发人员手动设置。尽管从一个状态到另一个状态的所有转换组合都是可能的,但是有一些是没有意义的。例如,将一个实体从Added状态转换到Deleted状态是没有意义的,反之亦然。下图展示了所有的状态以及一个实体如何从一个状态传递到另一个状态。
图中描述的非常清晰了,唯一需要说明的就是图中所示的所有方法都属于ObjectContext或者ObjectSet<T>类。下面我们详细的看一下各种状态。
DETACHED状态
当一个实体处于Detached状态,它没有绑定到上下文(context),所以它的状态是不能被追踪的。它可以释放,修改以及和其他类组合或者其他任何你可能需要的方式使用。因为它没有上下文追踪它,它对EF没有意义。
由于上下文不能追踪你代码中任何对象的创建,因此,Detached是新创建实体的默认状态。即使你在上下文的using块中实例化实体也是如此。当追踪被禁用时,Detached还是从数据库中检索的实体的状态。
UNCHANGED状态
当实体是Unchanged状态,它被绑定到上下文,但是它还没有被修改。默认情况下,从数据库中检索的实体是这种状态。
当实体附加到(使用Attach方法)上下文时,它同样是Unchanged状态。上下文不能追踪它不引用的对象的变化,所以当它们附加到上下文,它们是Unchanged状态。
ADDED状态
当实体处于Added状态,你有很少的选择。实际上,你只能使用Detach方法将它从上下文中分离。
当然,即使你修改了一些属性,状态依然保持为Added,因为转换到Modified,Unchanged或者Deleted没有意义——它是一个新实体并且在数据库中没有对应的行。这是处在这些状态的前提条件。
MODIFIED状态
当实体是Modified时,这意味着它处在Unchanged状态,然后改变了一些属性。
一个实体进入Modified状态后,它可以转换到Detached或者Deleted状态,但是即使手动重置初始值也不能使它回滚到Unchanged状态(除非从上下文分离再附加到上下文)。它也不能变成Added状态(除非从上下文分离再添加一个实体到上下文,因为在数据库中已经存在这个ID的行,当持久化它时,就会得到一个运行时异常)。
DELETED状态
实体进入Deleted状态因为它处于Unchanged或者Modified状态,然后使用了DeleteObject。这是最严格的状态,因为除了转换成Detached状态,从这种状态转换成任何其他的状态都是没有意义的。
下一篇文章学习如何管理实体的状态。