Click to Rate and Give Feedback
MSDN
MSDN Library
Visual Studio 2008
Visual Studio
Accessing Data
ADO.NET
Feature Reference
Object Services
Customizing Objects
 Implementing Custom Data Class Inte...
Implementing Custom Data Class Interfaces (Entity Framework)

The recommended way to use custom data classes with an Entity Data Model (EDM) is to inherit from EntityObject and ComplexObject. For cases when you cannot inherit from EntityObject and ComplexObject or when you need a higher degree of independence from the framework, the Entity Framework provides a set of custom data class interfaces. If you do not inherit from EntityObject, you must implement these interfaces to use custom data classes with an EDM. The specific interfaces that you implement depend on the requirements of your custom data classes and your application.

IEntityWithChangeTracker

Required for change tracking. Enables Object Services to track changes to the object.

Object Services provides objects with the IEntityChangeTracker interface to enable objects to report changes. IEntityWithChangeTracker defines the SetChangeTracker method. This method specifies the IEntityChangeTracker used to report changes. For more information, see Reporting Changes in Custom Data Classes (Entity Framework).

IEntityWithKey

Optional. Exposes the entity key to Object Services for improved performance.

IEntityWithKey defines the EntityKey property. Object Services uses the EntityKey property to manage objects in the object context.

If you choose not to implement IEntityWithKey, you will see decreased performance and increased memory usage when loading related objects, attaching objects to an object context, or any operation that requires a key.

IEntityWithRelationships

Required for entities with associations. Enables Object Services to manage relationships between objects.

IEntityWithRelationships defines the RelationshipManager property. Object Services uses the RelationshipManager property to access the RelationshipManager used to manage relationships to other objects.

For more information, see How to: Implement Custom Data Class Interfaces (Entity Framework).

Like custom data classes that inherit from EntityObject, classes that implement these interfaces must meet the following requirements:

  • There must be an object for each entity type that is defined in the conceptual schema definition language (CSDL) file.

  • The namespace, classes, and data properties must have the appropriate EDM attributes applied.

  • The names of the namespace, classes, and data properties that have EDM attributes applied must match the names in the corresponding CSDL file.

For more information, see Customizing Objects (Entity Framework).

The following example shows the code that is required to implement these interfaces for an Order object, where Order is based on the SalesOrderHeader table.

Visual Basic
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.
        ' 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
C#
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.
        // 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;
    }
}

Complex Types

Complex types are non-scalar properties of entity types that enable scalar properties to be organized within entities. For more information, see Complex Type (EDM). Tracking changes in complex type objects requires you to write custom change tracking code. Therefore, we recommend inheriting from EntityObject and ComplexObject when possible. There are no custom data class interfaces to implement for complex type objects. However, you can use the following procedure to implement change tracking with complex type objects that do not inherit from ComplexObject.

NoteNote

If you choose to implement custom data class interfaces for objects but also to inherit from ComplexObject, you must still implement custom change tracking as described in the following procedure.

To implement change tracking for complex type objects

  1. Implement custom data interfaces for entity types. For more information, see How to: Implement Custom Data Class Interfaces (Entity Framework).

  2. Ensure that complex types are correctly defined in the conceptual and mapping sections of the EDM. For more information, see Complex Type (EDM).

  3. Define an abstract base class called ComplexTypeChangeTracker.

    Visual Basic
    ' 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
    C#
    // 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. Define the complex type class, which inherits from ComplexTypeChangeTracker, and apply the EdmComplexTypeAttribute.

    Visual Basic
    <EdmComplexTypeAttribute(NamespaceName:="Microsoft.Samples.Entity", Name:="OrderInfo")> _
    Partial Public Class OrderInfo
        Inherits ComplexTypeChangeTracker
    C#
    [EdmComplexTypeAttribute(NamespaceName = "Microsoft.Samples.Entity", Name = "OrderInfo")]
    public partial class OrderInfo : ComplexTypeChangeTracker
    {
  5. In the complex type class, override the SetComplexChangeTracker method.

    Visual Basic
    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
    C#
    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. Implement standard change tracking on the scalar properties of the complex type. For more information, see Reporting Changes in Custom Data Classes (Entity Framework).

  7. Apply the EdmComplexPropertyAttribute to the complex property in the entity type, and add a call to SetComplexChangeTracker to reset the change tracker when the complex property changes.

    Visual Basic
    <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
    C#
    [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. Repeat steps 4-7 for each complex property.

  9. In the System.Data.Objects.DataClasses.IEntityWithChangeTracker.SetChangeTracker(System.Data.Objects.DataClasses.IEntityChangeTracker) implementation for the entity type, insert a call to SetComplexChangeTracker to set the change tracker. Do this once for each complex property in the type.

    Visual Basic
    ' 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
    C#
    // Every time the change tracker is set, we must also set all the 
    // complex type change trackers.
    if (_extendedInfo != null)
    {
        _extendedInfo.SetComplexChangeTracker("ExtendedInfo", _changeTracker);
    }

See Also

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement
Page view tracker