附加和分离对象(实体框架)
在实体框架 中,可以将对象附加到对象上下文中,或将其从对象上下文中分离。 附加到对象上下文的对象可以由该对象上下文进行跟踪和管理。 对象上下文不能引用已分离的对象,但它们的资源可由 .NET Framework 回收。 本主题介绍如何附加和分离对象以及执行此类操作的注意事项。
附加对象
在实体框架 中的对象上下文内执行查询时,返回的对象将自动附加到对象上下文。 还可以将从源而不是从查询获得的对象附加到对象上下文。 您可以附加以前分离的对象、由 NoTracking 查询返回的对象或从对象上下文的外部获取的对象。 还可以附加存储在 ASP.NET 应用程序的视图状态中的对象或从远程方法调用或 Web 服务返回的对象。
使用下列方法之一将对象附加到对象上下文:
成员 | 说明 |
---|---|
System.Data.Objects.ObjectSet.AddObject( 或 System.Data.Objects.ObjectContext.AddObject(System.String,System.Object) |
将一个对象及其相关对象添加到 ObjectContext,并将实体对象设置为 Added 状态。 在此状态下,实体对象不必具有唯一键值。 系统会将临时键值分配给键属性,并在您保存了对象后使用数据源生成的值更新临时键值。 在添加了对象之后,相应地更改实体对象的状态。 |
System.Data.Objects.ObjectSet.Attach( 或 System.Data.Objects.ObjectContext.Attach(System.Data.Objects.DataClasses.IEntityWithKey) 和 |
将一个对象添加到 ObjectContext,并将该对象设置为 Unchanged 状态。 在 Unchanged 状态下,实体框架 会将实体键值视为最终的值。 如果某个特定类型的多个实体具有相同键值,实体框架 将会引发异常。 若要避免获得异常,请使用 AddObject 方法附加已分离的对象,然后相应地更改状态。 |
对象以 Unchanged 状态附加到对象上下文。 由于知道对象在已分离的状态下进行了修改,所以您需要更改对象的状态或关系,在这种情况下,请使用以下方法之一。
成员 | 说明 |
---|---|
将实体或关系更改为新状态(如 Added 或 Modified)。 此更改可能会对某个实体参与的关系产生影响。 例如,将某个实体迁移到 Added 状态也会将任何未更改的关系迁移到 Added 状态。 同样,将某个实体标记为 Modified 也会将所有标量值标记为 Modified。 还可使用 ObjectStateEntry 的 ChangeState 方法。 |
|
将两个实体之间的现有关系更改为指定状态。 如果实体间无任何关系,则此方法将创建一种处于指定状态的新关系。 对于基于外键关联的关系,不支持此方法。 有关更多信息,请参见定义和管理关系(实体框架)。 还可使用 ObjectStateEntry 的 ChangeObjectState 方法。 |
|
ChangeState |
根据 ObjectStateEntry 是对象还是关系,此方法的行为与 ChangeObjectState 或 ChangeRelationshipState 的行为相同。 |
将单个属性设置为 Modified 状态。 当您知道哪些属性经过了修改时(而不是设置要修改的整个实体时)使用此方法。 |
如果正附加的对象已更新了属性值,请使用以下方法之一:
成员 | 说明 |
---|---|
System.Data.Objects.ObjectSet.ApplyCurrentValues( 或 System.Data.Objects.ObjectContext.ApplyCurrentValues.String, |
将标量值从提供的对象复制到 ObjectContext 中具有相同键的对象中。 任何与原始值不同的值都将标记为已修改。 如果您具有一个包含当前值的图形,并且希望应用原始值,请调用 ApplyOriginalValues 方法。 还可使用 ObjectStateEntry 的 ApplyCurrentValues 方法。 |
System.Data.Objects.ObjectSet.ApplyOriginalValues( 或 System.Data.Objects.ObjectContext.ApplyOriginalValues.String, |
将标量值从提供的对象复制到 ObjectContext 中具有相同键的对象的原始值集中。 任何与当前值不同的值都将标记为已修改。 还可使用 ObjectStateEntry 的 ApplyOriginalValues 方法。 |
SetModifiedProperty |
将单个属性设置为 Modified 状态。 当您知道哪些属性经过了修改时(而不是设置要修改的整个实体时)使用此属性。 |
获取表示与此 ObjectStateEntry 关联的对象的可更新原始值的 OriginalValueRecord 实例。 使用返回的 OriginalValueRecord 实例可单独读取或更新该对象的原始属性。 |
|
获取表示与此 ObjectStateEntry 关联的对象的当前值的 CurrentValueRecord 实例。 使用返回的 CurrentValueRecord 实例可单独读取或更新该对象的当前属性。 |
附加对象的注意事项
将对象附加到对象上下文时应注意以下注意事项:
如果被附加的对象具有相关对象,则这些对象也被附加到对象上下文。
如果附加的对象不在数据源中,则在执行 SaveChanges 时不会添加该对象。 在这种情况下,如果对属性进行了更改,则在执行 SaveChanges 时在服务器上会引发异常。 若要添加对象,请使用 System.Data.Objects.ObjectSet.AddObject( 或 System.Data.Objects.ObjectContext.AddObject(System.String,System.Object)
如果附加的对象与其他对象相关,则必须采用定义和管理关系(实体框架)中描述的方法之一显式定义该关系。 有关更多信息,请参见如何:附加相关对象(实体框架)。
传递到 Attach 方法的对象必须具有有效的 EntityKey 值。 如果对象没有有效的 EntityKey 值,请使用 AttachTo 方法指定实体集的名称。
当被附加的对象与对象上下文中已存在的另一个对象具有相同的 EntityKey 时,将发生 InvalidOperationException。 如果上下文中具有相同键的对象处于 Added 状态时,不会发生此错误。
分离对象
在实体框架 应用程序中,可以将对象从对象上下文中分离。 您可能会分离对象以保留资源,这是因为在相同的对象上下文中执行重复的查询会增加对象上下文的内存需求。 可以通过执行具有 NoTracking 的 MergeOption 值的查询避免对象附加到对象上下文,或者通过调用 System.Data.Objects.ObjectSet.Detach( 或 System.Data.Objects.ObjectContext.Detach(System.Object) 方法并将引用传递给要分离的对象来分离对象,如下面示例所示:
' Detach the first SalesOrderDetail in the collection.
context.Detach(order.SalesOrderDetails.First())
// Detach the first SalesOrderDetail in the collection.
context.Detach(order.SalesOrderDetails.First());
分离对象的注意事项
在分离对象时,应考虑以下注意事项:
Detach 只影响传递给该方法的特定对象。 如果要分离的对象在对象上下文中具有相关对象,则那些相关对象不会分离。
在独立关联中,不会为已分离的对象保留关系信息。
分离对象后,不会维护对象状态信息。 这包括所跟踪的更改和临时键值。
分离对象不影响数据源中的数据。
在分离操作期间不会对标识关系中的指令和引用约束强制执行级联删除。
应对照执行分离操作时所需要的附加处理量来考察分离对象所带来的优势。 当用户数据的范围已经更改(例如,用一组不同的数据显示新窗体)时,应该考虑创建一个新的 ObjectContext 实例,而不只是从现有 ObjectContext 分离对象。
有关更多信息,请参见如何:从对象上下文分离对象(实体框架)。