實作自訂資料類別介面 (Entity Framework)
搭配 Entity Data Model (EDM) 使用自訂資料類別的建議方式是從 EntityObject 和 ComplexObject 繼承。如果您無法從 EntityObject 和 ComplexObject 繼承,或是您需要獨立於架構之外的更高獨立性,Entity Framework 提供了一組自訂資料類別介面。如果您不是繼承自 EntityObject,您必須實作這些介面來搭配 EDM 使用自訂資料類別。您實作的特定介面取決於自訂資料類別和應用程式的需求而定。
IEntityWithChangeTracker
變更追蹤所需。可讓物件服務追蹤物件的變更。物件服務會針對 IEntityChangeTracker 介面提供物件,好讓物件報告變更。IEntityWithChangeTracker 會定義 SetChangeTracker 方法。此方法會指定用來報告變更的 IEntityChangeTracker。如需詳細資訊,請參閱報告自訂資料類別中的變更 (Entity Framework)。
IEntityWithKey
選擇項。公開實體索引鍵給物件服務,以改善效能。IEntityWithKey 會定義 EntityKey 屬性。物件服務會使用 EntityKey 屬性,在物件內容中管理物件。
如果您選擇不實作 IEntityWithKey,則載入相關物件、將物件附加至物件內容,或進行需要索引鍵的任何作業時,您將會發現效能降低和記憶體用量增加。
IEntityWithRelationships
具有關聯的實體都必須具備。可讓物件服務管理物件之間的關聯性。IEntityWithRelationships 會定義 RelationshipManager 屬性。物件服務會使用 RelationshipManager 屬性來存取用來管理與其他物件之關聯性的 RelationshipManager。
如需詳細資訊,請參閱 HOW TO:實作自訂資料類別介面 (Entity Framework)。
就像繼承自 EntityObject 的自訂資料類別一樣,實作這些介面的類別必須符合以下需求:
概念結構定義語言 (CSDL) 檔中定義的每一個實體類型都必須有一個物件。
命名空間、類別和資料屬性都必須套用適當的 EDM 屬性。
已套用 EDM 屬性 (Attribute) 的命名空間、類別和資料屬性 (Property) 名稱都必須符合對應 CSDL 檔案中的名稱。
如需詳細資訊,請參閱自訂物件 (Entity Framework)。
下列範例顯示針對 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,您仍然必須實作自訂變更追蹤,如下列程序所述。 |
若要針對複雜類型物件實作變更追蹤
針對實體類型實作自訂資料介面。如需詳細資訊,請參閱 HOW TO:實作自訂資料類別介面 (Entity Framework)。
確定複雜類型已正確定義在 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); }
在複雜類型的純量屬性上實作標準變更追蹤。如需詳細資訊,請參閱報告自訂資料類別中的變更 (Entity Framework)。
將 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); }