Implémentation d'interfaces de classes de données personnalisées (Entity Framework)

La méthode recommandée pour utiliser les classes de données personnalisées avec un modèle EDM (Entity Data Model) consiste à hériter d'EntityObject et de ComplexObject. Pour les cas où vous ne pouvez pas hériter d'EntityObject et de ComplexObject ou lorsque vous avez besoin d'un degré plus élevé d'indépendance par rapport à l'infrastructure, Entity Framework fournit un jeu d'interfaces de classes de données personnalisées. Si vous n'héritez pas d'EntityObject, vous devez implémenter ces interfaces pour utiliser les classes de données personnalisées avec un modèle EDM. Les interfaces spécifiques que vous implémentez dépendent des besoins de vos classes de données personnalisées et de votre application.

  • IEntityWithKey
    Facultatif. Expose la clé d'entité à Object Services pour améliorer les performances.

    IEntityWithKey définit la propriété EntityKey. Object Services utilise la propriété EntityKey pour gérer les objets dans le contexte de l'objet.

    Si vous choisissez de ne pas implémenter IEntityWithKey, vous constaterez une dégradation des performances et une augmentation de l'utilisation de la mémoire lors du chargement d'objets connexes, de l'attachement d'objets à un contexte d'objet ou de toute opération qui requiert une clé.

  • IEntityWithRelationships
    Obligatoire pour les entités présentant des associations. Permet à Object Services de gérer les relations entre les objets.

    IEntityWithRelationships définit la propriété RelationshipManager. Object Services utilise la propriété RelationshipManager pour accéder au RelationshipManager utilisé pour gérer les relations aux autres objets.

Pour plus d'informations, voir Procédure : implémenter des interfaces de classes de données personnalisées (Entity Framework).

Comme les classes de données personnalisées qui héritent d'EntityObject, les classes qui implémentent ces interfaces doivent satisfaire les exigences suivantes :

  • Un objet doit exister pour chaque type d'entité défini dans le fichier CSDL (Conceptual Schema Definition Language).

  • L'espace de noms, les classes et les propriétés des données doivent avoir les attributs EDM appropriés appliqués.

  • Les noms de l'espace de noms, des classes et des propriétés des données qui ont des attributs EDM appliqués doivent correspondre aux noms dans le fichier CSDL correspondant.

Pour plus d'informations, voir Personnalisation des objets (Entity Framework).

L'exemple suivant illustre le code requis pour implémenter ces interfaces pour un objet Order, où Order est basé sur la table 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;
    }
}

Types complexes

Les types complexes sont des propriétés non scalaires des types d'entités qui permettent d'organiser les propriétés scalaires au sein des entités. Pour plus d'informations, voir Type complexe (EDM). Le suivi des modifications d'objets de type complexe exige que vous écriviez un code personnalisé de suivi des modifications. Par conséquent, nous recommandons d'hériter d'EntityObject et de ComplexObject lorsque cela est possible. Il n'y a pas d'interfaces de classes de données personnalisées à implémenter pour les objets de type complexe. Toutefois, vous pouvez utiliser la procédure suivante pour implémenter le suivi des modifications avec des objets de type complexe qui n'héritent pas de ComplexObject.

NoteRemarque

Si vous choisissez d'implémenter des interfaces de classes de données personnalisées pour des objets mais également d'hériter de ComplexObject, vous devez encore implémenter un suivi des modifications personnalisé tel que décrit dans la procédure ci-dessous.

Pour implémenter le suivi des modifications pour des objets de type complexe

  1. implémentez des interfaces de classes de données personnalisées pour les types d'entité. Pour plus d'informations, voir Procédure : implémenter des interfaces de classes de données personnalisées (Entity Framework).

  2. Assurez-vous que les types complexes sont définis correctement dans les sections conceptuelles et de mappage du modèle EDM. Pour plus d'informations, voir Type complexe (EDM).

  3. Définissez une classe de base abstraite nommée 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. Définissez la classe de type complexe, qui hérite de ComplexTypeChangeTracker, et appliquez 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. Dans la classe de type complexe, remplacez la méthode 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. Implémentez le suivi des modifications standard sur les propriétés scalaires du type complexe. Pour plus d'informations, voir Création de rapports de modifications dans les classes de données personnalisées (Entity Framework).

  7. Appliquez EdmComplexPropertyAttribute à la propriété complexe dans le type d'entité et ajoutez un appel à SetComplexChangeTracker pour réinitialiser le dispositif de suivi des modifications lorsque la propriété complexe change.

    <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. Répétez les étapes 4 à 7 pour chaque propriété complexe.

  9. Dans la mise en œuvre de System.Data.Objects.DataClasses.IEntityWithChangeTracker.SetChangeTracker(System.Data.Objects.DataClasses.IEntityChangeTracker) pour le type d'entité, insérez un appel à SetComplexChangeTracker pour définir le dispositif de suivi des modifications. Procédez ainsi une fois pour chaque propriété complexe dans le type.

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

Voir aussi

Référence

EDM Generator (EdmGen.exe)

Concepts

Vue d'ensemble d'Object Services (Entity Framework)