使用自跟踪实体

在实体框架 应用程序中,对象上下文负责跟踪对象图中的实体中的更改。但是,在 N 层方案中,对象上下文有可能在修改实体的层上不可用。从 .NET Framework 版本 4 开始,自跟踪实体可帮助跟踪任意层中的更改。

Ff407090.note(zh-cn,VS.100).gif注意:
仅当对象上下文在更改对象图的层上不可用时使用自跟踪实体。如果对象上下文可用,则使用 EntityObject 派生类型或“纯旧式”CLR 对象 (POCO) 类型或 POCO 代理类型。有关更多信息,请参见使用对象(实体框架)

从 Microsoft Visual Studio 2010 开始,**“ADO.NET 自跟踪实体生成器”**模板可生成自跟踪实体。此模板项可生成两个 .tt(文本模板)文件:<模型名称>.tt 和 <模型名称>.Context.tt。<模型名称>.tt 文件可生成实体类型、包含自跟踪实体使用的更改跟踪逻辑的 Helper 类以及允许设置自跟踪实体的状态的扩展方法。<模型名称>.Context.tt 文件可生成类型化 ObjectContext 以及包含 ObjectContextObjectSet 类的 ApplyChanges 方法的扩展类。这些方法检查自跟踪实体图中包含的更改跟踪信息,以推断在数据库中保存这些更改所必须执行的一组操作。有关更多信息,请参见 ADO.NET Self-Tracking Entity Generator Template

Ff407090.Important(zh-cn,VS.100).gif 注意:
服务不应信任从不受信任的客户端或通过不受信任的通道检索或更新数据的请求。客户端必须经身份验证:应使用安全通道或消息信封。必须验证客户端更新或检索数据的请求,从而确保这些请求符合对于给定方案合法的预期更改。

Ff407090.Important(zh-cn,VS.100).gif 注意:
避免将敏感信息用作实体键(例如身份证号码)。这样可降低意外地将自跟踪实体图中的敏感信息序列化到不完全可信的客户端的可能性。通过使用独立关联,实体中与正在序列化的键相关的原始键也可能会发送到客户端。

自跟踪实体扩展方法

可以将以下扩展方法应用于自跟踪实体。如果您想要对一组实体而不只是一个实体执行这些操作,请参见使用自跟踪实体集了解更多信息。

StartTracking 方法

StartTracking 方法指示实体上的更改跟踪器开始记录应用到实体的任何更改。这包括对标量属性、集合以及其他实体引用的更改。当通过 Windows Communication Foundation (WCF) 将自跟踪实体反序列化到客户端时,这些实体会自动开始跟踪。在以下方案中,还会为最新创建的实体启用跟踪:

  • 在新实体和已在跟踪更改的实体之间创建关系。

  • 对实体调用 MarkAs[State]AcceptChanges 方法。

StopTracking 方法

StopTracking 方法停止记录更改。

MarkAs 方法

所有 MarkAs 方法都启用跟踪。通过这些扩展方法,可以方便地将实体的状态显式更改为 AddedModifiedDeletedUnchanged

MarkAs[State] 方法返回其应用到的、已修改状态的同一个实体。下面的示例将实体的状态修改为 Unchanged

department.Course = new Course { CourseID = courseID }.MarkAsUnchanged();

MarkAsAdded 方法将实体的状态更改为 Added。新创建的自跟踪实体具有 Added 状态,并且不会启用更改跟踪。

MarkAsDeleted 方法将实体的状态更改为 Deleted。此方法还会清除标记为删除的实体的导航属性。如果导航属性指向引用对象,则设置为 null。如果导航属性表示集合,则调用 Clear 方法。对集合中某对象调用 MarkAsDeleted 时,会将该对象从集合中移除。若要将某集合中的每个对象都标记为已删除,则标记该集合副本中的对象。若要获取集合副本,则对集合调用 ToArray()ToList() 方法,如下面的示例所示:

List<Course> courses = department.Courses.ToList();

foreach (var c in courses)

{

// Mark each course in the department as Deleted.

c.MarkAsDeleted();

}

MarkAsModified 方法将实体的状态更改为 Modified。另外,修改已启用更改跟踪的实体的某个属性值时也会将状态设置为 Modified

MarkAsUnchanged 方法将实体的状态更改为 Unchanged。此外,AcceptChanges 还会清除实体的更改跟踪信息,并将实体的状态更改为 Unchanged

AcceptChanges

AcceptChanges 方法清除实体的更改跟踪信息,并将实体的状态更改为 Unchanged。如果要重置某个关系的状态,请针对参与该关系的两个实体调用 AcceptChanges

ObjectContext 扩展方法

ApplyChanges 方法检查自跟踪实体图中包含的更改跟踪信息,并推断在数据库中反映这些更改所必须执行的操作集。存在两种 ApplyChanges 方法,一种方法用于 ObjectContext,另一种方法用于 ObjectSet

Ff407090.note(zh-cn,VS.100).gif注意:
为了避免向客户端层传播包含敏感数据的异常消息,应将服务器层上对 ApplyChangesSaveChanges 的调用包装到异常处理代码中。

使用自跟踪实体时的注意事项

使用自跟踪实体时应考虑以下事项:

  • 确保您的客户端项目具有对包含实体类型的程序集的引用。如果您只将服务引用添加到客户端项目,则客户端项目将使用 WCF 代理类型,而不是实际的自跟踪实体类型。这意味着您将不能获得管理客户端上实体跟踪的自动通知功能。如果您不希望包含实体类型,则必须手动设置客户端的更改跟踪信息以便将更改发送回服务。

  • 对服务操作的调用应是无状态的,并且创建一个新的对象上下文实例。还建议您在 using 块中创建对象上下文。

  • 如果您在将客户端上已修改的关系图发送到服务后想要在客户端上继续使用同一张关系图,则您必须手动循环访问该关系图,并对每个对象调用 AcceptChanges 方法以重置更改跟踪器。如果关系图中的对象包含具有数据库生成的值(例如,标识值或并发值)的属性,则在调用 SaveChanges 方法后,实体框架 将这些属性的值替换为数据库生成的值。可实现服务操作以返回保存的对象或生成的属性值列表,从而将对象发送回客户端。然后,客户端需要将对象实例或对象属性值替换为从服务操作返回的对象或属性值。

  • 合并多个服务请求的关系图可能会在生成的关系图中引入具有重复键值的对象。当您调用 ApplyChanges 方法时,实体框架 不会移除具有重复键的对象,但会引发异常。为了避免生成具有重复键值的关系图,请遵循以下博客中所述的模式之一:自跟踪实体:ApplyChanges 和重复实体

  • 当您通过设置外键属性更改对象之间的关系时,引用导航属性设置为 Null,并且不同步到客户端上的相应主体实体。将关系图附加到对象上下文之后(例如,调用 ApplyChanges 方法之后),同步外键属性和导航属性。

    如果您已对外键关系指定级联删除,则引用导航属性与相应主体对象不同步会是个问题。如果您删除了主体,则这种删除将不会传播到依赖对象。如果您已指定级联删除,则使用导航属性更改关系,而不是设置外键属性。

  • 执行延迟加载时不启用自跟踪实体。

  • 从**“ADO.NET 自跟踪实体生成器”**模板生成的代码不支持二进制序列化和针对 ASP.NET 状态管理对象的序列化。但是,您可以自定义此模板来添加二进制序列化支持。有关更多信息,请参见将二进制序列化和 ViewState 用于自跟踪实体

另请参见

任务

演练:序列化自跟踪实体(实体框架)

其他资源

使用自跟踪实体集
Silverlight 中的自跟踪实体
将二进制序列化和 ViewState 用于自跟踪实体