Compartir a través de


Implementar interfaces de clases de datos personalizadas (Entity Framework)

La manera recomendada de usar clases de datos personalizadas con un modelo Entity Data Model (EDM) es heredar de EntityObject y ComplexObject. En los casos en los que no se puede heredar de EntityObject y ComplexObject, o cuando se necesita un grado más alto de independencia del marco de trabajo, Entity Framework proporciona un conjunto de interfaces de clases de datos personalizadas. Si no hereda de EntityObject, debe implementar estas interfaces para usar clases de datos personalizadas con un EDM. Las interfaces concretas que implemente dependerán de los requisitos de las clases de datos personalizadas y de su aplicación.

  • IEntityWithKey
    Opcional. Expone la clave de entidad de Servicios de objeto para mejorar el rendimiento.

    IEntityWithKey define la propiedad EntityKey. Servicios de objeto usa la propiedad EntityKey para administrar objetos en el contexto del objeto.

    Si elige no implementar IEntityWithKey, observará que el rendimiento disminuye y el uso de memoria aumenta al cargar los objetos relacionados, al asociar los objetos a un contexto del objeto o al realizar cualquier operación que requiera una clave.

  • IEntityWithRelationships
    Se requiere para las entidades con asociaciones. Habilita Servicios de objeto para administrar las relaciones entre los objetos.

    IEntityWithRelationships define la propiedad RelationshipManager. Servicios de objeto usa la propiedad RelationshipManager para tener acceso al RelationshipManager que se usa para administrar las relaciones con otros objetos.

Para obtener más información, vea Cómo implementar interfaces de clases de datos personalizadas (Entity Framework).

Al igual que las clases de datos personalizadas que heredan de EntityObject, las clases que implementan estas interfaces deben cumplir los requisitos siguientes:

  • Debe haber un objeto para cada tipo de entidad que está definido en el archivo de lenguaje de definición de esquemas conceptuales (CSDL).

  • El espacio de nombres, las clases y las propiedades de datos deben tener aplicados los atributos de EDM adecuados.

  • Los nombres del espacio de nombres, las clases y las propiedades de datos que tienen aplicados los atributos de EDM deben coincidir con los nombres del archivo CSDL correspondiente.

Para obtener más información, vea Personalizar objetos (Entity Framework).

En el ejemplo siguiente se muestra el código que se requiere para implementar estas interfaces para un objeto Order, donde Order está basado en la tabla 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;
    }
}

Tipos complejos

Los tipos complejos son propiedades no escalares de tipos de entidad que permiten organizar las propiedades escalares dentro de las entidades. Para obtener más información, vea Tipo complejo (EDM). El seguimiento de los cambios en los objetos de tipos complejos requiere que se escriba código de seguimiento de cambios personalizado. Por lo tanto, se recomienda heredar de EntityObject y ComplexObject cuando sea posible. No hay ninguna interfaz de clase de datos personalizada que implementar para los objetos de tipos complejos. Sin embargo, puede utilizar el procedimiento siguiente para implementar el seguimiento de cambios con objetos de tipos complejos que no hereden de ComplexObject.

Nota

Si decide implementar las interfaces de clases de datos personalizadas para los objetos pero también para heredar de ComplexObject, debe seguir implementando el seguimiento de cambios personalizado según se describe en el procedimiento siguiente.

Para implementar el seguimiento de cambios en los objetos de tipos complejos

  1. Implemente interfaces de datos personalizadas para los tipos de entidad. Para obtener más información, vea Cómo implementar interfaces de clases de datos personalizadas (Entity Framework).

  2. Asegúrese de que los tipos complejos se definen correctamente en las secciones conceptual y de asignación del EDM. Para obtener más información, vea Tipo complejo (EDM).

  3. Defina una clase base abstracta denominada 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. Defina la clase de tipo complejo, que hereda de ComplexTypeChangeTracker, y aplique el 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. En la clase del tipo complejo, invalide el método 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. Implemente el seguimiento de cambios estándar en las propiedades escalares del tipo complejo. Para obtener más información, vea Notificar los cambios en clases de datos personalizadas (Entity Framework).

  7. Aplique el EdmComplexPropertyAttribute a la propiedad compleja en el tipo de entidad y agregue una llamada a SetComplexChangeTracker para restablecer el seguidor de cambios cuando la propiedad compleja cambie.

    <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. Repita los pasos 4 a 7 con cada propiedad compleja.

  9. En la implementación de System.Data.Objects.DataClasses.IEntityWithChangeTracker.SetChangeTracker(System.Data.Objects.DataClasses.IEntityChangeTracker) para el tipo de entidad, inserte una llamada a SetComplexChangeTracker para establecer el seguidor de cambios. Haga esto una vez con cada propiedad compleja del tipo.

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

Vea también

Referencia

Generador de EDM (EdmGen.exe)

Conceptos

Información general de Servicios de objeto (Entity Framework)