实现自定义数据类接口(实体框架)
若要将自定义数据类用于 Entity Data Model (EDM),建议从 EntityObject 和 ComplexObject 继承。针对无法从 EntityObject 和 ComplexObject 继承,或者需要更加独立于框架的情况,Entity Framework 提供了一组自定义数据类接口。如果不从 EntityObject 继承,则必须实现这些接口,才能将自定义数据类用于 EDM。要实现的特定接口取决于自定义数据类和应用程序的要求。
IEntityWithChangeTracker
对于更改跟踪是必需的。使对象服务可以跟踪对对象的更改。对象服务向对象提供 IEntityChangeTracker 接口,使对象能够报告更改。IEntityWithChangeTracker 定义 SetChangeTracker 方法。此方法指定用于报告更改的 IEntityChangeTracker。有关更多信息,请参见报告自定义数据类中的更改(实体框架)。
IEntityWithKey
可选。向对象服务公开实体键以提高性能。IEntityWithKey 定义 EntityKey 属性。对象服务使用 EntityKey 属性来管理对象上下文中的对象。
如果选择不实现 IEntityWithKey,则在加载相关对象、将对象附加到对象上下文或执行需要键的任何操作时,性能将会下降,内存占用量会增加。
IEntityWithRelationships
对于具有关联的实体,这是必需的。使对象服务能够管理对象之间的关系。IEntityWithRelationships 定义 RelationshipManager 属性。对象服务使用 RelationshipManager 属性来访问用于管理与其他对象的关系的 RelationshipManager。
有关更多信息,请参见如何:实现自定义数据类接口(实体框架)。
与从 EntityObject 继承的自定义数据类相似,实现这些接口的类必须满足以下要求:
在概念性架构定义语言 (CSDL) 文件中定义的每个实体类型都必须有一个对象。
命名空间、类和数据属性 (Property) 必须应用适当的 EDM 属性 (Attribute)。
应用了 EDM 属性 (Attribute) 的命名空间、类和数据属性 (Property) 的名称必须与相应的 CSDL 文件中的名称相匹配。
有关更多信息,请参见自定义对象(实体框架)。
下面的示例演示为 Order 对象实现这些接口所需的代码,其中 Order 基于 SalesOrderHeader 表。
Dim _changeTracker As IEntityChangeTracker = Nothing
' Specify the IEntityChangeTracker to use for tracking changes.
Private Sub SetChangeTracker(ByVal changeTracker As IEntityChangeTracker) _
Implements IEntityWithChangeTracker.SetChangeTracker
_changeTracker = changeTracker
' Every time the change tracker is set, we must also set all the
' complex type change trackers.
If Not _extendedInfo Is Nothing Then
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker)
End If
End Sub
Dim _entityKey As EntityKey = Nothing
' Define the EntityKey property for the class.
Property EntityKey() As EntityKey Implements IEntityWithKey.EntityKey
Get
Return _entityKey
End Get
Set(ByVal value As EntityKey)
' Set the EntityKey property, if it is not set.
' Report the change if the change tracker exists.
If Not _changeTracker Is Nothing Then
_changeTracker.EntityMemberChanging(StructuralObject.EntityKeyPropertyName)
_entityKey = value
_changeTracker.EntityMemberChanged(StructuralObject.EntityKeyPropertyName)
Else
_entityKey = value
End If
End Set
End Property
Dim _relationships As RelationshipManager = Nothing
' Define a relationship manager for the class.
ReadOnly Property RelationshipManager() As RelationshipManager _
Implements IEntityWithRelationships.RelationshipManager
Get
If _relationships Is Nothing Then
_relationships = RelationshipManager.Create(Me)
End If
Return _relationships
End Get
End Property
IEntityChangeTracker _changeTracker = null;
// Specify the IEntityChangeTracker to use for tracking changes.
void IEntityWithChangeTracker.SetChangeTracker(IEntityChangeTracker changeTracker)
{
_changeTracker = changeTracker;
// Every time the change tracker is set, we must also set all the
// complex type change trackers.
if (_extendedInfo != null)
{
_extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker);
}
}
EntityKey _entityKey = null;
// Define the EntityKey property for the class.
EntityKey IEntityWithKey.EntityKey
{
get
{
return _entityKey;
}
set
{
// Set the EntityKey property, if it is not set.
// Report the change if the change tracker exists.
if (_changeTracker != null)
{
_changeTracker.EntityMemberChanging(StructuralObject.EntityKeyPropertyName);
_entityKey = value;
_changeTracker.EntityMemberChanged(StructuralObject.EntityKeyPropertyName);
}
else
{
_entityKey = value;
}
}
}
RelationshipManager _relationships = null;
// Define a relationship manager for the class.
RelationshipManager IEntityWithRelationships.RelationshipManager
{
get
{
if (null == _relationships)
_relationships = RelationshipManager.Create(this);
return _relationships;
}
}
复杂类型
复杂类型是实体类型的非标量属性,实体类型允许在实体内组织标量属性。有关更多信息,请参见复杂类型 (EDM)。若要跟踪复杂类型对象中的更改,需要编写自定义更改跟踪代码。为此,建议尽可能从 EntityObject 和 ComplexObject 继承。没有自定义数据类接口可以实现复杂类型对象。不过,使用下面的过程可以实现不从 ComplexObject 继承的复杂类型对象的更改跟踪。
注意 |
---|
如果选择为对象实现自定义数据类接口,同时还从 ComplexObject 继承,则必须还要实现自定义更改跟踪,如下面的过程所述。 |
实现复杂类型对象的更改跟踪
实现实体类型的自定义数据接口。有关更多信息,请参见如何:实现自定义数据类接口(实体框架)。
确保在 EDM 的概念性部分和映射部分中正确定义了复杂类型。有关更多信息,请参见复杂类型 (EDM)。
定义名为 ComplexTypeChangeTracker 的抽象基类。
' Base class for complex types that implements change tracking. Public MustInherit Class ComplexTypeChangeTracker Protected _complexChangeTracker As IEntityChangeTracker = Nothing Private _rootComplexPropertyName As String ' Gets an IEntityChangeTracker to call for properties change. ' You must do this in order to track changes. Public Overridable Sub SetComplexChangeTracker( _ ByVal rootComplexPropertyName As String, _ ByVal complexChangeTracker As IEntityChangeTracker) _rootComplexPropertyName = rootComplexPropertyName _complexChangeTracker = complexChangeTracker End Sub ' Protected method that is called before the change for change tracking ' each of the scalar properties in the complex type. Protected Sub ReportMemberChanging(ByVal scalarPropertyName As String) If Not _complexChangeTracker Is Nothing Then _complexChangeTracker.EntityComplexMemberChanging( _ _rootComplexPropertyName, Me, scalarPropertyName) End If End Sub ' Protected method that is called after the change for change tracking ' each of the scalar properties in the complex type. Protected Sub ReportMemberChanged(ByVal scalarPropertyName As String) If Not _complexChangeTracker Is Nothing Then _complexChangeTracker.EntityComplexMemberChanged( _ _rootComplexPropertyName, Me, scalarPropertyName) End If End Sub End Class
// Base class for complex types that implements change tracking. public abstract class ComplexTypeChangeTracker { protected IEntityChangeTracker _complexChangeTracker = null; private string _rootComplexPropertyName; // Gets an IEntityChangeTracker to call for properties change. // You must do this in order to track changes. virtual public void SetComplexChangeTracker(string rootComplexPropertyName, IEntityChangeTracker complexChangeTracker) { _rootComplexPropertyName = rootComplexPropertyName; _complexChangeTracker = complexChangeTracker; } // Protected method that is called before the change for change tracking // each of the scalar properties in the complex type. protected void ReportMemberChanging(string scalarPropertyName) { if (null != _complexChangeTracker) { _complexChangeTracker.EntityComplexMemberChanging(_rootComplexPropertyName, this, scalarPropertyName); } } // Protected method that is called after the change for change tracking // each of the scalar properties in the complex type. protected void ReportMemberChanged(string scalarPropertyName) { if (null != _complexChangeTracker) { _complexChangeTracker.EntityComplexMemberChanged(_rootComplexPropertyName, this, scalarPropertyName); } } }
定义从 ComplexTypeChangeTracker 继承的复杂类型类,并应用 EdmComplexTypeAttribute。
<EdmComplexTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="OrderInfo")> _ Partial Public Class OrderInfo Inherits ComplexTypeChangeTracker
[EdmComplexTypeAttribute(NamespaceName = "Microsoft.Samples.Edm", Name = "OrderInfo")] public partial class OrderInfo : ComplexTypeChangeTracker {
在复杂类型类中,重写 SetComplexChangeTracker 方法。
Public Overrides Sub SetComplexChangeTracker(ByVal rootComplexPropertyName As String, _ ByVal changeTracker As IEntityChangeTracker) ' Call SetChangeTracker on the base class to set the change tracker ' and the name of the root complex type property on the entity. MyBase.SetComplexChangeTracker(rootComplexPropertyName, changeTracker) End Sub
override public void SetComplexChangeTracker(string rootComplexPropertyName, IEntityChangeTracker changeTracker) { // Call SetChangeTracker on the base class to set the change tracker // and the name of the root complex type property on the entity. base.SetComplexChangeTracker(rootComplexPropertyName, changeTracker); }
对复杂类型的标量属性实现标准更改跟踪。有关更多信息,请参见报告自定义数据类中的更改(实体框架)。
对实体类型的复杂属性应用 EdmComplexPropertyAttribute,并添加对 SetComplexChangeTracker 的调用,以便在复杂属性更改时重置更改跟踪器。
<EdmComplexPropertyAttribute()> _ Public Property ExtendedInfo() As OrderInfo Get Return _extendedInfo End Get Set(ByVal value As OrderInfo) ' For a complex type any changes in the complex type ' properties all get tracked together. ' The change tracker may be Nothing during object materialization. If Not _changeTracker Is Nothing Then ' Since this is a complex property, we need to reset the change ' tracker on the complex type. If Not _extendedInfo Is Nothing Then ' Reset the change tracker. _extendedInfo.SetComplexChangeTracker("ExtendedInfo", Nothing) End If ' Report the change. _changeTracker.EntityMemberChanging("ExtendedInfo") _extendedInfo = value _changeTracker.EntityMemberChanging("ExtendedInfo") Else _extendedInfo = value End If ' Rest the change tracker. Complex type property cannot be Nothing. If Not _extendedInfo Is Nothing Then _extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker) End If End Set End Property
[EdmComplexPropertyAttribute()] public OrderInfo ExtendedInfo { get { return _extendedInfo; } set { // For a complex type any changes in the complex type // properties all get tracked together. // The change tracker may be null during object materialization. if (_changeTracker != null) { // Since this is a complex property, we need to reset the change // tracker on the complex type. if (_extendedInfo != null) { // Reset the change tracker. _extendedInfo.SetComplexChangeTracker("ExtendedInfo", null); } // Report the change. _changeTracker.EntityMemberChanging("ExtendedInfo"); _extendedInfo = value; _changeTracker.EntityMemberChanged("ExtendedInfo"); } else { _extendedInfo = value; } // Reset the change tracker. Complex type property cannot be null. if (_extendedInfo != null) { _extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker); } } }
对每个复杂属性重复步骤 4-7。
在实体类型的 System.Data.Objects.DataClasses.IEntityWithChangeTracker.SetChangeTracker(System.Data.Objects.DataClasses.IEntityChangeTracker) 实现中,插入对 SetComplexChangeTracker 的调用以设置更改跟踪器。对类型中的每个复杂属性执行一次此步骤。
' Every time the change tracker is set, we must also set all the ' complex type change trackers. If Not _extendedInfo Is Nothing Then _extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker) End If
// Every time the change tracker is set, we must also set all the // complex type change trackers. if (_extendedInfo != null) { _extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker); }