다음을 통해 공유


사용자 지정 데이터 클래스의 변경 내용 보고(Entity Framework)

개체 서비스는 IEntityChangeTracker 인터페이스를 제공하며, 이 인터페이스는 데이터 클래스에서 데이터 속성 변경을 보고할 때 사용합니다. EntityObjectIEntityWithChangeTrackerSetChangeTracker 메서드를 구현합니다. 이 메서드는 개체 서비스에서 호출되며, 변경을 보고하는 데 개체가 사용하는 IEntityChangeTracker 인스턴스를 지정합니다. IEntityChangeTracker에서 지원하는 변경 보고 모델에서는 보류 중인 속성 변경을 보고하고 속성을 설정한 다음 변경이 완료되었음을 보고합니다.

EntityObject에서 상속되지 않은 사용자 지정 데이터 클래스의 변경을 보고하려면 이 클래스가 IEntityWithChangeTracker를 구현해야 합니다. 자세한 내용은 사용자 지정 데이터 클래스 인터페이스 구현(Entity Framework)을 참조하십시오.

변경 내용을 보고할 때 다음 사항을 고려해야 합니다.

  • 속성 값을 설정하기 전에는 속성을 변경 중으로 보고하고, 속성 값을 설정한 후에는 변경됨으로 보고해야 합니다.

  • EntityKey 속성의 변경을 보고해야 합니다. EntityKey 속성이 설정된 후에는 이 속성을 변경 중으로 보고하는 응용 프로그램 코드는 InvalidOperationException을 발생시킵니다. 그러나 EntityKey 속성이 설정된 후 개체 서비스가 이를 변경해야 하는 경우가 있습니다. 이 속성의 변경을 보고하면 개체 서비스는 이 속성을 설정할 시점을 확인할 수 있습니다.

  • 속성을 변경 중으로 보고하고, 이후에 이를 변경됨으로 보고하지 않을 수 있습니다. 하지만 이 경우, 변경은 추적되지 않습니다.

  • 어떤 속성을 변경 중으로 보고하기 전에 그 속성을 변경됨으로 보고하거나 잘못된 속성 이름이 전달될 경우 InvalidOperationException이 발생합니다. 이는 여러 속성이 변경 중으로 보고되고 이후에 변경됨으로 보고되지 않는 경우에 발생할 수 있습니다. 그 이유는 맨 처음 변경 중으로 보고되었던 속성에 대해 변경된 속성의 유효성을 검사할 때 마지막 속성이 인식되기 때문입니다.

EntityObject 및 ComplexObject에서 상속할 때 속성 변경 보고

사용자 지정 데이터 클래스가 EntityObject 또는 ComplexObject에서 상속하는 경우 속성 변경을 보고하려면 ReportPropertyChangingReportPropertyChanged 메서드를 호출해야 합니다.

EntityObject에서 상속할 때 속성 변경을 보고하려면

  1. EntityObjectSystem.Data.Objects.DataClasses.EntityObject.ReportPropertyChanging(System.String) 메서드를 호출하여 변경 중인 속성의 이름을 전달합니다.

    이 메서드는 속성의 현재 값을 캐시하고 이 값이 속성의 원래 값으로 사용됩니다.

  2. 속성을 적절히 설정합니다.

  3. EntityObjectSystem.Data.Objects.DataClasses.EntityObject.ReportPropertyChanged(System.String) 메서드를 호출하여 변경된 속성의 이름을 전달합니다.

    이 메서드는 속성의 보류 중인 변경 내용이 이제 완료되었음을 개체 서비스에 알립니다. 그럼 개체 서비스에서 해당 속성을 수정된 것으로 표시합니다.

ComplexObject에서 상속할 때 속성 변경을 보고하려면

  1. ComplexObjectSystem.Data.Objects.DataClasses.ComplexObject.ReportPropertyChanging(System.String) 메서드를 호출하여 변경 중인 속성의 이름을 전달합니다. 이 메서드는 속성의 현재 값을 캐시하고 이 값이 속성의 원래 값으로 사용됩니다.

  2. 속성을 적절히 설정합니다.

  3. ComplexObjectSystem.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 메서드를 호출하여 변경된 최상위 엔터티 속성의 이름, 변경된 속성을 포함하는 복합 개체 인스턴스, 복합 형식에 대해 변경된 속성의 이름 등을 전달합니다. 이 메서드는 속성의 현재 값을 캐시하고 이 값이 속성의 원래 값으로 사용됩니다.

  2. 속성을 적절히 설정합니다.

  3. EntityComplexMemberChanged 메서드를 호출하여 변경된 최상위 엔터티 속성의 이름, 변경된 속성을 포함하는 복합 개체 인스턴스, 복합 형식에 대해 변경된 속성의 이름 등을 전달합니다. 이 메서드는 속성의 보류 중인 변경 내용이 이제 완료되었음을 개체 서비스에 알립니다. 그럼 개체 서비스에서 해당 속성을 수정된 것으로 표시합니다.

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)