Partager via


Création de rapports de modifications dans les classes de données personnalisées (Entity Framework)

Object Services fournit l'interface IEntityChangeTracker, qui est utilisée par les classes de données pour créer des rapports sur les modifications apportées aux propriétés des données. EntityObject implémente la méthode SetChangeTracker d'IEntityWithChangeTracker. Cette méthode est appelée par Object Services pour spécifier l'instance d'IEntityChangeTracker qu'un objet utilise pour signaler les modifications. Le modèle de rapport de modifications pris en charge par IEntityChangeTracker implique de signaler une modification en attente d'une propriété, de définir la propriété, puis de signaler la fin de la modification.

Pour signaler les modifications dans des classes de données personnalisées qui n'héritent pas d'EntityObject, ces classes doivent implémenter IEntityWithChangeTracker. Pour plus d'informations, voir Implémentation d'interfaces de classes de données personnalisées (Entity Framework).

Vous devez tenir compte des points suivants lors de la création de rapports de modifications :

  • Vous devez signaler la modification d'une propriété avant de définir la valeur de la propriété, puis signaler que la propriété a été modifiée une fois que la valeur de la propriété a été définie.

  • Vous devez signaler les modifications de la propriété EntityKey. Une fois que la propriété EntityKey a été définie, le code d'application qui signale la modification en cours de cette propriété génère un InvalidOperationException. Toutefois, dans certains cas, Object Services doit être en mesure de modifier la propriété EntityKey après sa définition. En signalant les modifications de cette propriété, Object Services est en mesure de déterminer quand il convient de définir cette propriété.

  • Vous pouvez signaler la modification en cours d'une propriété sans signaler ensuite qu'elle a été modifiée. Toutefois, dans ce cas, la modification ne sera pas suivie.

  • Un InvalidOperationException est déclenché lorsque vous signalez qu'une propriété a été modifiée avant de signaler la modification en cours de la même propriété, ou lorsqu'un nom de propriété non valide est passé. Cela peut se produire lorsque la modification en cours de plusieurs propriétés est signalée sans que la modification effective de ces propriétés soit signalée ensuite. Cela est dû au fait que seule la dernière propriété est reconnue lorsque la propriété modifiée est validée par rapport à la propriété dont la modification en cours a été signalée en premier.

Création de rapport sur les modifications des propriétés lors d'un héritage à partir d'EntityObject et de ComplexObject

Lorsqu'une classe de données personnalisée hérite d'EntityObject ou de ComplexObject, vous devez appeler les méthodes ReportPropertyChanging et ReportPropertyChanged pour signaler les modifications des propriétés.

Pour signaler les modifications d'une propriété lors d'un héritage à partir de EntityObject

  1. Appelez la méthode System.Data.Objects.DataClasses.EntityObject.ReportPropertyChanging(System.String) sur EntityObject, en passant le nom de la propriété en cours de modification.

    Cela met en cache la valeur actuelle de la propriété, qui est utilisée comme valeur d'origine pour la propriété.

  2. Définissez la propriété selon vos besoins.

  3. Appelez la méthode System.Data.Objects.DataClasses.EntityObject.ReportPropertyChanged(System.String) sur EntityObject, en passant le nom de la propriété modifiée.

    Cela notifie Object Services que la modification en attente sur la propriété est maintenant terminée. Object Services marque ensuite la propriété comme ayant été modifiée.

Pour signaler les modifications d'une propriété lors d'un héritage à partir de ComplexObject

  1. Appelez la méthode System.Data.Objects.DataClasses.ComplexObject.ReportPropertyChanging(System.String) sur ComplexObject, en passant le nom de la propriété en cours de modification. Cela met en cache la valeur actuelle de la propriété, qui est utilisée comme valeur d'origine pour la propriété.

  2. Définissez la propriété selon vos besoins.

  3. Appelez la méthode System.Data.Objects.DataClasses.ComplexObject.ReportPropertyChanged(System.String) sur ComplexObject, en passant le nom de la propriété modifiée. Cela notifie Object Services que la modification en attente sur la propriété est maintenant terminée. Object Services marque ensuite la propriété comme ayant été modifiée.

L'exemple suivant montre comment signaler les modifications lors de la définition de la propriété Status scalaire sur l'objet Order :

<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");
        }
    }
}

Création d'un rapport sur les modifications des propriétés lors de l'implémentation d'IEntityWithChangeTracker

Lorsqu'une classe de données personnalisée implémente IEntityWithChangeTracker, vous devez appeler des méthodes de création de rapport de modifications sur IEntityChangeTracker avant et après la modification de la propriété pour signaler correctement la modification.

Pour signaler les modifications d'une propriété lors de l'implémentation d'IEntityWithChangeTracker

  1. Appelez la méthode EntityMemberChanging, en passant le nom de la propriété en cours de modification. La valeur actuelle de la propriété, qui est utilisée comme valeur d'origine pour la propriété, est alors mise en cache.

  2. Définissez la propriété selon vos besoins.

  3. Appelez la méthode EntityMemberChanged, en passant le nom de la propriété modifiée.

  4. Cela notifie Object Services que la modification en attente sur la propriété est maintenant terminée. Object Services marque ensuite la propriété comme ayant été modifiée.

Pour signaler les modifications d'une propriété lors de l'implémentation d'IEntityWithChangeTracker sur un type complexe

  1. Appelez la méthode EntityComplexMemberChanging, en passant le nom de la propriété d'entité de niveau supérieur qui a changé, l'instance d'objet complexe qui contient la propriété modifiée et le nom de la propriété modifiée sur le type complexe. La valeur actuelle de la propriété, qui est utilisée comme valeur d'origine pour la propriété, est alors mise en cache.

  2. Définissez la propriété selon vos besoins.

  3. Appelez la méthode EntityComplexMemberChanged, en passant le nom de la propriété d'entité de niveau supérieur qui a changé, l'instance d'objet complexe qui contient la propriété modifiée et le nom de la propriété modifiée sur le type complexe. Cela notifie Object Services que la modification en attente sur la propriété est maintenant terminée. Object Services marque ensuite la propriété comme ayant été modifiée.

Dans certaines situations, une instance d'IEntityChangeTracker peut ne pas être disponible. Cela peut se produire lorsqu'un objet est détaché du contexte d'objet ou lorsqu'une requête est exécutée à l'aide de l'option NoTracking. Vous devez rechercher une instance d'IEntityChangeTracker avant d'appeler les méthodes de création de rapport de modifications.

L'exemple suivant montre une classe abstraite ComplexTypeChangeTracker qui correspond à la classe de base pour tous les types complexes dérivés. Cette classe implémente le suivi des modifications pour les type complexes.

' 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);
        }
    }
}

L'exemple suivant montre comment utiliser les méthodes de l'exemple précédent pour rendre compte des modifications lorsque la propriété scalaire Status est définie sur l'objet Order :

<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;
            }
        }
    }
}

Voir aussi

Concepts

Personnalisation des objets (Entity Framework)