實作自訂資料類別介面 (Entity Framework)

搭配 Entity Data Model (EDM) 使用自訂資料類別的建議方式是從 EntityObjectComplexObject 繼承。如果您無法從 EntityObjectComplexObject 繼承,或是您需要獨立於架構之外的更高獨立性,Entity Framework 提供了一組自訂資料類別介面。如果您不是繼承自 EntityObject,您必須實作這些介面來搭配 EDM 使用自訂資料類別。您實作的特定介面取決於自訂資料類別和應用程式的需求而定。

  • IEntityWithKey
    選擇項。公開實體索引鍵給物件服務,以改善效能。

    IEntityWithKey 會定義 EntityKey 屬性。物件服務會使用 EntityKey 屬性,在物件內容中管理物件。

    如果您選擇不實作 IEntityWithKey,則載入相關物件、將物件附加至物件內容,或進行需要索引鍵的任何作業時,您將會發現效能降低和記憶體用量增加。

如需詳細資訊,請參閱 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)。追蹤複雜類型物件中的變更時,您需要撰寫自訂變更追蹤程式碼。因此,建議您在可能的情況下最好能從 EntityObjectComplexObject 繼承。無法針對複雜類型物件實作任何自訂資料類別介面。但是,您可以使用以下程序,使用非繼承自 ComplexObject 的複雜類型物件來實作變更追蹤。

Note附註

如果您選擇針對物件來實作自訂資料類別介面,但是也要繼承自 ComplexObject,您仍然必須實作自訂變更追蹤,如下列程序所述。

若要針對複雜類型物件實作變更追蹤

  1. 針對實體類型實作自訂資料介面。如需詳細資訊,請參閱 HOW TO:實作自訂資料類別介面 (Entity Framework)

  2. 確定複雜類型已正確定義在 EDM 的概念和對應區段中。如需詳細資訊,請參閱複雜類型 (EDM)

  3. 定義稱為 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);
            }
        }
    }
    
  4. 定義繼承自 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
    {
    
  5. 在複雜類型類別中,覆寫 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);
    }
    
  6. 在複雜類型的純量屬性上實作標準變更追蹤。如需詳細資訊,請參閱報告自訂資料類別中的變更 (Entity Framework)

  7. 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);
            }
        }
    }
    
  8. 針對每一個複雜屬性重複步驟 4-7。

  9. 在實體類型的 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);
    }
    

另請參閱

參考

EDM 產生器 (EdmGen.exe)

概念

物件服務概觀 (Entity Framework)