共用方式為


報告自訂資料類別中的變更 (Entity Framework)

物件服務提供了 IEntityChangeTracker 介面,資料類別會使用這個介面來報告對資料屬性所做的變更。EntityObject 會實作 IEntityWithChangeTrackerSetChangeTracker 方法。物件服務會呼叫這個方法來指定讓物件用來報告變更的 IEntityChangeTracker 執行個體。IEntityChangeTracker 所支援的變更報告模型牽涉到報告屬性的暫止變更、設定屬性,然後報告變更完成。

若要變更不會繼承自 EntityObject 之自訂資料類別中的變更,這些類別必須實作 IEntityWithChangeTracker。如需詳細資訊,請參閱實作自訂資料類別介面 (Entity Framework)

下列考量適用於報告變更時:

  • 在您設定屬性值之前,應該要將屬性報告為變更中,然後在設定屬性值以後,應該將屬性報告為已變更。

  • 您必須將變更報告到 EntityKey 屬性。在設定 EntityKey 屬性之後,將此屬性報告為變更中的應用程式程式碼會造成 InvalidOperationException。但是在某些類別中,物件服務在設定 EntityKey 屬性之後,必須能夠加以變更。在報告這個屬性的變更之後,物件服務便能夠判斷何時要設定這個屬性。

  • 您可以將屬性報告為變更中,而之後不需要將它報告為已變更。但是,在此情況下將不會追蹤變更。

  • 當您將屬性報告為變更中之前,或是在傳遞了無效的屬性名稱時,如果將相同的屬性報告為已變更,就會引發 InvalidOperationException。當您將多個屬性報告為變更中,而之後沒有將它報告為已變更時,可能會發生這個情況。這是因為針對第一次報告為變更中的屬性驗證已變更的屬性時,只會辨認最後一個屬性。

繼承自 EntityObject 和 ComplexObject 時,報告屬性變更

當自訂資料類別繼承自 EntityObjectComplexObject 時,您必須呼叫 ReportPropertyChangingReportPropertyChanged 方法來報告屬性變更。

繼承自 EntityObject 時,報告屬性的變更

  1. EntityObject 上呼叫 System.Data.Objects.DataClasses.EntityObject.ReportPropertyChanging(System.String) 方法,傳遞變更中屬性的名稱。

    這樣會快取目前的屬性值,這個值會當做屬性的原始值使用。

  2. 適當地設定屬性。

  3. EntityObject 上呼叫 System.Data.Objects.DataClasses.EntityObject.ReportPropertyChanged(System.String) 方法,傳遞已變更的屬性名稱。

    這樣會通知物件服務,告知現在已完成屬性上的暫止變更。然後物件服務會將屬性標示為已修改。

繼承自 ComplexObject 時,報告屬性的變更

  1. ComplexObject 上呼叫 System.Data.Objects.DataClasses.ComplexObject.ReportPropertyChanging(System.String) 方法,傳遞變更中屬性的名稱。這樣會快取目前的屬性值,這個值會當做屬性的原始值使用。

  2. 適當地設定屬性。

  3. ComplexObject 上呼叫 System.Data.Objects.DataClasses.ComplexObject.ReportPropertyChanged(System.String) 方法,傳遞已變更的屬性名稱。這樣會通知物件服務,告知現在已完成屬性上的暫止變更。然後物件服務會將屬性標示為已修改。

下列範例將示範如何在設定 Order 物件的純量 Status 屬性時報告變更:

<EdmScalarPropertyAttribute(IsNullable:=False)> _
Public Property Status() As Byte
    Get
        Return _status
    End Get
    Set(ByVal value As Byte)
        If _status <> value Then
            ReportPropertyChanging("Status")
            _status = value
            ReportPropertyChanged("Status")
        End If
    End Set
End Property
[EdmScalarPropertyAttribute(IsNullable = false)]
public byte Status
{
    get 
    {
        return _status;
    }
    set
    {
        if (_status != value)
        {
            ReportPropertyChanging("Status");
            _status = value;
            ReportPropertyChanged("Status");
        }
    }
}

當實作 IEntityWithChangeTracker 時,報告屬性變更

當自訂資料類別實作 IEntityWithChangeTracker 時,您必須在屬性變更的前後於 IEntityChangeTracker 上呼見變更報告方法,才能正確地報告變更。

在實作 IEntityWithChangeTracker 時,報告屬性的變更

  1. 呼叫 EntityMemberChanging 方法,傳遞變更中屬性的名稱。這樣會快取屬性的目前值,這個值會當做屬性的原始值使用。

  2. 適當地設定屬性。

  3. 呼叫 EntityMemberChanged 方法,傳遞已變更的屬性名稱。

  4. 這樣會通知物件服務,告知現在已完成屬性上的暫止變更。然後物件服務會將屬性標示為已修改。

在複雜類型上實作 IEntityWithChangeTracker 時,報告屬性的變更

  1. 呼叫 EntityComplexMemberChanging 方法,傳遞已變更的最上層實體屬性名稱、包含已變更之屬性的 Complex 物件執行個體,以及在複雜類型上變更的屬性名稱。這樣會快取屬性的目前值,這個值會當做屬性的原始值使用。

  2. 適當地設定屬性。

  3. 呼叫 EntityComplexMemberChanged 方法,傳遞已變更的最上層實體屬性名稱、包含已變更之屬性的 Complex 物件執行個體,以及在複雜類型上變更的屬性名稱。這樣會通知物件服務,告知現在已完成屬性上的暫止變更。然後物件服務會將屬性標示為已修改。

在某些狀況下,可能無法使用 IEntityChangeTracker 的執行個體。當從物件內容中斷連結物件,或是使用 NoTracking 選項執行查詢時,可能會發生這個情況。在您呼叫變更報告方法之前,必須檢查是否有 IEntityChangeTracker 的執行個體。

以下範例示範抽象類別 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);
        }
    }
}

以下範例示範在 Order 物件上設定純量 Status 屬性時,如何使用前面範例中的方法報告變更:

<EdmScalarPropertyAttribute()> _
Public Property Comment() As String
    Get
        Return _comment
    End Get
    Set(ByVal value As String)
        ' Validate the value before setting it.
        If (value <> Nothing) AndAlso value.Length > 128 Then
            Throw New ApplicationException(String.Format( _
                      My.Resources.propertyNotValidString, _
                      "Comment", "128"))
        End If
        If _comment <> value Then
            ' Report the change if the change tracker exists.
            If Not _complexChangeTracker Is Nothing Then
                ReportMemberChanging("Comment")
                _comment = value
                ReportMemberChanged("Comment")
            Else
                _comment = value
            End If
        End If
    End Set
End Property
[EdmScalarPropertyAttribute()]
public string Comment
{
    get
    {
        return _comment;
    }
    set
    {
        // Validate the value before setting it.
        if ((value != null) && value.Length > 128)
        {
            throw new ApplicationException(string.Format(
                      Properties.Resources.propertyNotValidString,
                      new string[3] { value, "Comment", "128" }));
        }
        if (_comment != value)
        {
            // Report the change if the change tracker exists.
            if (_complexChangeTracker != null)
            {
                ReportMemberChanging("Comment");
                _comment = value;
                ReportMemberChanged("Comment");
            }
            else
            {
                _comment = value;
            }
        }
    }
}

另請參閱

概念

自訂物件 (Entity Framework)