Freigeben über


Implementieren von Schnittstellen für benutzerdefinierte Datenklassen (Entity Framework)

Die empfohlene Vorgehensweise für die Verwendung benutzerdefinierter Datenklassen mit einem Entity Data Model (EDM) ist das Erben von EntityObject und ComplexObject. In Fällen, in denen das Erben von EntityObject und ComplexObject nicht möglich ist, oder wenn eine größere Unabhängigkeit vom Framework erforderlich ist, bietet das Entity Framework einen Satz von Schnittstellen für benutzerdefinierte Datenklassen. Wenn Sie nicht von EntityObject erben, müssen Sie diese Schnittstellen implementieren, um benutzerdefinierte Datenklassen mit einem EDM zu verwenden. Welche spezifischen Schnittstellen Sie implementieren, ist von den Anforderungen der benutzerdefinierten Datenklassen und der Anwendung abhängig.

  • IEntityWithKey
    Optional. Macht aus Leistungsgründen den Entitätsschlüssel für Object Services verfügbar.

    IEntityWithKey definiert die EntityKey-Eigenschaft. Die EntityKey-Eigenschaft wird von Object Services verwendet, um Objekte im Objektkontext zu verwalten.

    Wenn Sie IEntityWithKey nicht implementieren, führt dies zu erheblichen Leistungseinbußen und erhöhtem Speicherbedarf beim Laden verbundener Objekte, beim Anfügen von Objekten an einen Objektkontext und bei allen Vorgängen, für die ein Schlüssel erforderlich ist.

  • IEntityWithRelationships
    Für Entitäten mit Zuordnungen erforderlich. Ermöglicht Object Services, Beziehungen zwischen Objekten zu verwalten.

    IEntityWithRelationships definiert die RelationshipManager-Eigenschaft. Object Services greift mit der RelationshipManager-Eigenschaft auf den RelationshipManager zu, mit dem Beziehungen zu anderen Objekten verwaltet werden.

Weitere Informationen finden Sie unter Gewusst wie: Implementieren von Schnittstellen für benutzerdefinierte Datenklassen (Entity Framework).

Genau wie benutzerdefinierte Datenklassen, die von EntityObject erben, müssen Klassen, die diese Schnittstellen implementieren, die folgenden Anforderungen erfüllen:

  • Es muss für jeden in der CSDL-Datei definierten Entitätstyp ein Objekt vorhanden sein.

  • Auf den Namespace, die Klassen und die Dateneigenschaften müssen die entsprechenden EDM-Attribute angewendet werden.

  • Die Namen des Namespaces, der Klassen und der Dateneigenschaften mit angewendeten EDM-Attributen müssen mit den Namen in der entsprechenden CSDL-Datei übereinstimmen.

Weitere Informationen finden Sie unter Anpassen von Objekten (Entity Framework).

Das folgende Beispiel zeigt den erforderlichen Code zum Implementieren dieser Schnittstellen für ein Order-Objekt. Dabei basiert Order auf der SalesOrderHeader-Tabelle.

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

Komplexe Typen

Komplexe Typen sind nicht skalare Eigenschaften von Entitätstypen, mit deren Hilfe skalare Eigenschaften in Entitäten organisiert werden können. Weitere Informationen finden Sie unter Komplexer Typ (EDM). Um in Objekten komplexer Typen Änderungen nachzuverfolgen, müssen Sie benutzerdefinierten Code zur Änderungsnachverfolgung schreiben. Aus diesem Grund wird empfohlen, wenn möglich von EntityObject und ComplexObject zu erben. Für Objekte komplexer Typen müssen keine benutzerdefinierten Schnittstellen für Datenklassen implementiert werden. Sie können mit dem folgenden Verfahren jedoch eine Änderungsnachverfolgung für Objekte komplexer Typen implementieren, die nicht von ComplexObject erben.

NoteHinweis

Wenn Sie für Objekte benutzerdefinierte Datenklassenschnittstellen implementieren, jedoch auch von ComplexObject erben, müssen Sie außerdem eine benutzerdefinierte Änderungsnachverfolgung implementieren, wie im folgenden Verfahren beschrieben.

So implementieren Sie die Änderungsnachverfolgung für Objekte komplexer Typen

  1. Implementieren Sie benutzerdefinierte Datenschnittstellen für Entitätstypen. Weitere Informationen finden Sie unter Gewusst wie: Implementieren von Schnittstellen für benutzerdefinierte Datenklassen (Entity Framework).

  2. Stellen Sie sicher, dass komplexe Typen im konzeptionellen Abschnitt und im Zuordnungsabschnitt des EDM ordnungsgemäß definiert werden. Weitere Informationen finden Sie unter Komplexer Typ (EDM).

  3. Definieren Sie die abstrakte Basisklasse 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. Definieren Sie die Klasse komplexen Typs, die von ComplexTypeChangeTracker erbt, und übernehmen Sie das 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. Überschreiben Sie in der Klasse komplexen Typs die SetComplexChangeTracker-Methode.

    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. Implementieren Sie für die skalaren Eigenschaften des komplexen Typs die Standardänderungsnachverfolgung. Weitere Informationen finden Sie unter Melden von Änderungen in benutzerdefinierten Datenklassen (Entity Framework).

  7. Wenden Sie das EdmComplexPropertyAttribute auf die komplexe Eigenschaft des Entitätstyps an, und fügen Sie einen Aufruf von SetComplexChangeTracker hinzu, um die Änderungsnachverfolgung zurückzusetzen, wenn sich die komplexe Eigenschaft ändert.

    <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. Wiederholen Sie die Schritte 4 bis 7 für jede komplexe Eigenschaft.

  9. Fügen Sie in der System.Data.Objects.DataClasses.IEntityWithChangeTracker.SetChangeTracker(System.Data.Objects.DataClasses.IEntityChangeTracker)-Implementierung für den Entitätstyp einen Aufruf von SetComplexChangeTracker ein, um die Änderungsnachverfolgung festzulegen. Führen Sie dies für jede komplexe Eigenschaft des Typs einmal durch.

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

Siehe auch

Verweis

EDM-Generator (EdmGen.exe)

Konzepte

Übersicht über Object Services (Entity Framework)