ObjectContext的一些知识

ObjectContext在EF中具有很重要的地位,并且我们在对EDM进行查询时都需要用到这个ObjectContext(每一个EDM的生成类都是继承自ObjectContext类的)。EF是面向对象在进行处理,查询是面向数据源在执行,而查询的结果的数据记录集并没有被返回,这些结果被具体化进入了CLR类型中后再被返回到客户端。这一过程被称作对象具体化(object materialization),由EF来处理。这些功能由Object Service来提供,具体实现在System.Data.Objects和System.Data.Objects.DataClasses名称空间中。

ObjectContext也位于并贯穿于这些名称空间中。这个类中封入了一个ObjectStateManager对象来负责跟踪对象的CRUD操作。在每个ObjectContext中只有一个ObjectStateManager。ObjectContext同时也为每个存储在ObjectContext缓存中的实体维护了一个ObjectStateEntry。

ObjectStateEntry

ObjectStateEntry类负责维护实体的状态和key信息。类的实例被创建用来缓存实体类型,并且具有独有的职责来负责跟踪和维持对象的原始数值、关系映射和对实体上修改的属性。ObjectStateEntry类同时跟踪EntityState(比如实体是否被拆分、删除、修改等等)和EntityKey的值。

在同一个ObjectStateManager中,一个ObjectStateEntry不能与其他的ObjectStateEntry具有相同的key。

当一个实体首次被创建时(进入ObjectContext缓存中),ObjectStateEntity也会抓取它的一个影像。这个影像中包含了实体的原始数值,并且一旦实体当前的值被修改后,也会同样被抓取保存。在实体进行修改的时刻,EntityState属性会被设置为如下的值:

·Detached:对象存在,但是没有正在被Object Services所跟踪。 ·Unchanged:对象至被装入context时或最后一次调用SaveChanges方法时还未被修改。 ·Added:对象是新被添加进context的,并且SaveChanges方法还未必调用。 ·Deleted:对象已经被移除了context。 ·Modified:对象已经改变了,但是SaveChanges方法还没有被调用。

幸好在处理实体时是由EF和ObjectContext替你去做全部的修改跟踪。一旦有修改变化发生在实体上面,ObjectContext会跟踪这些修改变化并自动设置EntityState的属性。

 

跟踪和保存修改变化

上面主要讨论了修改变化是如何通过EntityState被跟踪的,但是我们还需要深入一些来理解修改变化追踪是如何工作的。当一个新的对象被添加进ObjectQuery(通过查询返回),它也被添加进了对象缓存中。这个缓存由ObjectStateManager来负责维护。

以实体主键的方式确保一个唯一的对象实例,这个实例由ObjectServices来负责管理和缓存。默认情况下,查询仅仅返回那些还未被缓存的对象。这一功能是由MergeOption枚举来负责提供的,枚举成员主要如下:

·Append Only:默认行为。在context中已经存在的对象不从数据源加载。 ·OverwriteChanges:对象总是从数据源加载。属性修改变化迫使context中的对象由数据源的数值来覆盖。 ·PreserveChanges:对象总是从数据源加载。属性修改变化迫使对象被封存在context中。 ·NoTracking:对象不被ObjectStateManager跟踪,是被维护成一个拆分的状态。

 

在所有的实体修改变化发生后,这些修改变化将被引导回数据源中。要完成这一个过程需通过调用ObjectContext的SaveChanges方法。这一方法负责了持续的让实体修改数据源同时也重新设置好context的跟踪修改变化。

EF4中有很多的SaveChanges情况,在EF3.5时SaveChanges主要有两种构造,第一是SaveChanges()保存全部的数据更新并重新设置全部跟踪。第二是SaveChanges(Boolean)保存全部数据更新并选择性决定是否重新设置全部跟踪。

在EF4中SaveChanges(Boolean)的已经被抛弃了,取而代之的是一个新的SaveChanges(SaveOptions)构造型。这样SaveChanges方法就变成了如下两种构造: ·SaveChanges():保存全部的数据更新并重新设置全部跟踪。 ·SaveChanges(SaveOptions):由SaveOptions来决定保存全部的数据更新。 SaveOptions枚举的内容: ·AcceptAllChangesAfterSave:在所有修改变化被保存后,AcceptAllChangesAfterSave()被调用,来重新设置跟踪。 ·DetectChangesBeforeSave: 在修改变化被保存前,DetectChanges()方法被调用来同步对象的属性值。这些对象是在ObjectStateManager中被关联到context上的对象。 ·None: 修改变化被保存不调用DetectChanges()或AcceptAllChangesAfterSave()方法。 

SaveOptions重载应该用来确保要么DetectChanges在保存修改变化前被调用,要么AcceptAllChanges在保存修改变化到数据后被调用。为什么非要确保一个呢?DetectChanges用来保证所有的ObjectStateEntry的修改是明确的并同步了所有ObjectStateManager跟踪和管理的对象。AcceptAllChanges则允许所有关联到在ObjectStateManager中的实体上的修改变化。所以这样一来的结果是,确保了状态要么是detached要么是unchanged。而实际上,我们没有必要使用它们中的任意一个,因为这个枚举类型有一个更好的可以按位组合的FlagAttribute属性值。

posted on 2012-11-29 10:54  simonwonn  阅读(862)  评论(0编辑  收藏  举报

导航