Condividi tramite


How to: Implement Custom Data Class Interfaces (Entity Framework)

When you use custom data classes with an Entity Data Model (EDM), the classes must implement the following custom data class interfaces:

For more information, see Implementing Custom Data Class Interfaces (Entity Framework). You must also apply EDM attributes that map the custom classes and properties to entities defined in the conceptual schema definition language (CSDL) file. For more information, see How to: Map Custom Objects to Entities (Entity Framework).

Instead of directly implementing data class interfaces, you can also inherit from EntityObject. This is the recommended way to use custom data classes with an EDM. For more information, see Customizing Objects (Entity Framework) and How to: Inherit from the EntityObject and ComplexObject Base Classes (Entity Framework).

To implement custom data class interfaces

  1. Modify the definition of each custom data class so that it implements the IEntityWithChangeTracker, IEntityWithKey, and IEntityWithRelationships interfaces, as in the following example:

    <EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Entity", Name:="Order")> _
    Public Class Order
        Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
    
    [EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Entity", Name = "Order")]
    public class Order : IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
    
  2. (Optional) Explicitly implement the EntityKey property in each custom data class, as in the following example:

    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
    
    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;
            }
        }
    }
    
  3. Explicitly implement the SetChangeTracker method in each custom data class, as in the following example:

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

    This method is required to report changes in data properties to Object Services.

  4. For IEntityWithRelationships, explicitly implement the RelationshipManager property, as in the following example:

    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
    
    RelationshipManager _relationships = null;
    
    // Define a relationship manager for the class.
    RelationshipManager IEntityWithRelationships.RelationshipManager
    {
        get
        {
            if (null == _relationships)
                _relationships = RelationshipManager.Create(this);
            return _relationships;
        }
    }
    
  5. In the settable scalar properties of each data class, add a call to EntityMemberChanging before setting the property value, and add a call to EntityMemberChanged after the property is set. This is shown in the following example:

    <EdmScalarPropertyAttribute(IsNullable:=False)> _
            Public Property Status() As Byte
        Get
            Return _status
        End Get
        Set(ByVal value As Byte)
            If _status <> value Then
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Status")
                    _status = value
                    _changeTracker.EntityMemberChanged("Status")
                Else
                    _status = value
                End If
            End If
        End Set
    End Property
    
    [EdmScalarPropertyAttribute(IsNullable = false)]
    public byte Status
    {
        get 
        {
            return _status;
        }
        set
        {
            if (_status != value)
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("Status");
                    _status = value;
                    _changeTracker.EntityMemberChanged("Status");
                }
                else
                {
                    _status = value;
                }
            }
        }
    }
    
  6. In the settable complex properties of each data class, add a call to EntityComplexMemberChanging before setting the property value, and add a call to EntityComplexMemberChanged after the property is set.

Example

This example shows the custom data classes Order and LineItem and a complex type OrderInfo. These custom classes are mapped to the SalesOrderHeader and SalesOrderDetail tables in the AdventureWorks database. Both entity classes implement all three custom data class interfaces. The OrderInfo complex type class demonstrates a suggested change tracking implementation.

Option Explicit On
Option Strict On

Imports System
Imports System.Data.SqlTypes
Imports System.Collections.Generic
Imports System.Text
Imports System.Data
Imports System.Data.Objects.DataClasses
Imports System.Data.Metadata.Edm


<Assembly: EdmSchemaAttribute()> 
<Assembly: EdmRelationshipAttribute("Microsoft.Samples.Entity", _
    "LineItem_Order_OrderId", "Order", _
    RelationshipMultiplicity.One, GetType(Order), "LineItems", _
    RelationshipMultiplicity.Many, GetType(LineItem))> 
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Entity", Name:="Order")> _
Public Class Order
    Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey

    ' Define private property variables.
    Private _orderId As Integer
    Private _revision As Byte
    Private _orderDate As DateTime
    Private _dueDate As DateTime
    Private _shipDate As DateTime
    Private _onlineOrder As Boolean
    Private _status As Byte
    Private _customer As Integer
    Private _contact As Integer
    Private _billToAddress As Integer
    Private _shipToAddress As Integer
    Private _shipMethod As Integer
    Private _subTotal As Decimal
    Private _tax As Decimal
    Private _freight As Decimal
    Private _totalDue As Decimal
    Private _extendedInfo As OrderInfo
    Private _rowGuid As Guid
    Private _modifiedDate As DateTime


#Region "ExplicitImplementation"
    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
#End Region

    ' Public properties of the Order object.
    <EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
    Public Property OrderId() As Integer
        Get
            Return _orderId
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("OrderId")
                _orderId = value
                _changeTracker.EntityMemberChanged("OrderId")
            Else
                _orderId = value
            End If
        End Set
    End Property
    ' Navigation property that returns a collection of line items.
    <EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Entity", "LineItem_Order_OrderId", "LineItems")> _
    Public ReadOnly Property LineItems() As EntityCollection(Of LineItem)
        Get
            Return CType(Me, IEntityWithRelationships).RelationshipManager.GetRelatedCollection(Of LineItem) _
            ("LineItem_Order_OrderId", "LineItems")
        End Get
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Revision() As Byte
        Get
            Return _revision
        End Get
        Set(ByVal value As Byte)
            If _revision <> value Then
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Revision")
                    _revision = value
                    _changeTracker.EntityMemberChanged("Revision")
                Else
                    _revision = value
                End If
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property OrderDate() As Date
        Get
            Return _orderDate
        End Get
        Set(ByVal value As DateTime)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("OrderDate")
                _orderDate = value
                _changeTracker.EntityMemberChanged("OrderDate")
            Else
                _orderDate = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property DueDate() As Date
        Get
            Return _dueDate
        End Get
        Set(ByVal value As Date)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("DueDate")
                _dueDate = value
                _changeTracker.EntityMemberChanged("DueDate")
            Else
                _dueDate = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute()> _
    Public Property ShipDate() As Date
        Get
            Return _shipDate
        End Get
        Set(ByVal value As Date)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("ShipDate")
                _shipDate = value
                _changeTracker.EntityMemberChanged("ShipDate")
            Else
                _shipDate = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property OnlineOrder() As Boolean
        Get
            Return _onlineOrder
        End Get
        Set(ByVal value As Boolean)
            If Not _onlineOrder = value Then
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("OnlineOrder")
                    _onlineOrder = value
                    _changeTracker.EntityMemberChanged("OnlineOrder")
                Else
                    _onlineOrder = value
                End If
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
            Public Property Status() As Byte
        Get
            Return _status
        End Get
        Set(ByVal value As Byte)
            If _status <> value Then
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Status")
                    _status = value
                    _changeTracker.EntityMemberChanged("Status")
                Else
                    _status = value
                End If
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Customer() As Integer
        Get
            Return _customer
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("Customer")
                _customer = value
                _changeTracker.EntityMemberChanged("Customer")
            Else
                _customer = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Contact() As Integer
        Get
            Return _contact
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("Contact")
                _contact = value
                _changeTracker.EntityMemberChanged("Contact")
            Else
                _contact = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property BillToAddress() As Integer
        Get
            Return _billToAddress
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("BillToAddress")
                _billToAddress = value
                _changeTracker.EntityMemberChanged("BillToAddress")
            Else
                _billToAddress = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property ShipToAddress() As Integer
        Get
            Return _shipToAddress
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("ShipToAddress")
                _shipToAddress = value
                _changeTracker.EntityMemberChanged("ShipToAddress")
            Else
                _shipToAddress = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property ShipMethod() As Integer
        Get
            Return _shipMethod
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("ShipMethod")
                _shipMethod = value
                _changeTracker.EntityMemberChanged("ShipMethod")
            Else
                _shipMethod = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property SubTotal() As Decimal
        Get
            Return _subTotal
        End Get
        Set(ByVal value As Decimal)
            If _subTotal <> value Then
                ' Validate the value before setting it.
                If value < 0 Then
                    Throw New ApplicationException(String.Format( _
                              Errors.propertyNotValidNegative, _
                              value.ToString, "SubTotal"))
                End If
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("SubTotal")
                    _subTotal = value
                    _changeTracker.EntityMemberChanged("SubTotal")
                Else
                    _subTotal = value
                End If
                ' Recalculate the order total.
                CalculateOrderTotal()
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Tax() As Decimal
        Get
            Return _tax
        End Get
        Set(ByVal value As Decimal)
            ' Validate the value before setting it.
            If value < 0 Then
                Throw New ApplicationException(String.Format( _
                          Errors.propertyNotValidNegative, _
                          value.ToString(), "Tax"))
            End If
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("TaxAmt")
                _tax = value
                _changeTracker.EntityMemberChanged("TaxAmt")
            Else
                _tax = value
            End If

            ' Recalculate the order total.
            CalculateOrderTotal()
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Freight() As Decimal
        Get
            Return _freight
        End Get
        Set(ByVal value As Decimal)
            If _freight <> value Then
                ' Validate the value before setting it.
                If value < 0 Then
                    Throw New ApplicationException(String.Format( _
                              Errors.propertyNotValidNegative, _
                    value.ToString(), "Freight"))
                End If
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Freight")
                    _freight = value
                    _changeTracker.EntityMemberChanging("Freight")
                Else
                    _freight = value
                End If
                ' Recalculate the order total.
                CalculateOrderTotal()
            End If
        End Set
    End Property
    Public ReadOnly Property TotalDue() As Decimal
        Get
            Return _totalDue
        End Get
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property RowGuid() As Guid
        Get
            Return _rowGuid
        End Get
        Set(ByVal value As Guid)
                ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("RowGuid")
                _rowGuid = value
                _changeTracker.EntityMemberChanged("RowGuid")
            Else
                _rowGuid = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute()> _
   Public Property ModifiedDate() As Date
        Get
            Return _modifiedDate
        End Get
        Set(ByVal value As Date)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("ModifiedDate")
                _modifiedDate = value
                _changeTracker.EntityMemberChanged("ModifiedDate")
            Else
                _modifiedDate = value
            End If
        End Set
    End Property
    <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
    Private Sub CalculateOrderTotal()
        ' Update the total due as a sum of the other cost properties.
        _totalDue = _subTotal + _tax + _freight
    End Sub
End Class
' 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
<EdmComplexTypeAttribute(NamespaceName:="Microsoft.Samples.Entity", Name:="OrderInfo")> _
Partial Public Class OrderInfo
    Inherits ComplexTypeChangeTracker
    Private _orderNumber As String
    Private _purchaseOrder As String
    Private _accountNumber As String
    Private _comment As String
    Private _extendedInfo As OrderInfo

    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
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property OrderNumber() As String
        Get
            Return _orderNumber
        End Get
        Set(ByVal value As String)
            ' Validate the value before setting it.
            If value.Length > 25 Then
                Throw New ApplicationException(String.Format( _
                    Errors.propertyNotValidString, _
                    "OrderNumber", "25"))
            End If
            ' Report the change if the change tracker exists.
            If Not _complexChangeTracker Is Nothing Then
                ReportMemberChanging("OrderNumber")
                _orderNumber = value
                ReportMemberChanged("OrderNumber")
            Else
                _orderNumber = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute()> _
    Public Property PurchaseOrder() As String
        Get
            Return _purchaseOrder
        End Get
        Set(ByVal value As String)
            If (value <> Nothing) AndAlso value.Length > 25 Then
                Throw New ApplicationException(String.Format( _
                          Errors.propertyNotValidString, _
                          "PurchaseOrder", "25"))
            End If
            If _purchaseOrder <> value Then
                ' Report the change if the change tracker exists.
                If Not _complexChangeTracker Is Nothing Then
                    ReportMemberChanging("PurchaseOrder")
                    _purchaseOrder = value
                    ReportMemberChanged("PurchaseOrder")
                Else
                    _purchaseOrder = value
                End If
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute()> _
    Public Property AccountNumber() As String
        Get
            Return _accountNumber
        End Get
        Set(ByVal value As String)
            ' Validate the value before setting it.
            If (value <> Nothing) AndAlso value.Length > 15 Then
                Throw New ApplicationException(String.Format( _
                          Errors.propertyNotValidString, _
                          "AccountNumber", "15"))
            End If
            ' Report the change if the change tracker exists.
            If Not _complexChangeTracker Is Nothing Then
                ReportMemberChanging("AccountNumber")
                _accountNumber = value
                ReportMemberChanged("AccountNumber")
            Else
                _accountNumber = value
            End If
        End Set
    End Property
    <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( _
                          Errors.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
End Class
<EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Entity", Name:="LineItem")> _
Public Class LineItem
    Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey

    ' Define private property variables.
    Private _orderId As Integer
    Private _lineItemId As Integer
    Private _trackingNumber As String
    Private _quantity As Short
    Private _special As Integer
    Private _product As Integer
    Private _price As Decimal
    Private _discount As Decimal
    Private _total As Decimal
    Private _rowGuid As Guid
    Private _modifiedDate As DateTime

    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
    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
    ' Defines a navigation property to the Order class.
    <EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Entity", _
            "LineItem_Order_OrderId", "Order")> _
    Public Property Order() As Order
        Get
            Return CType(Me,  _
            IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of Order) _
            ("LineItem_Order_OrderId", "Order").Value
        End Get
        Set(ByVal value As Order)
            CType(Me,  _
            IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of Order) _
            ("LineItem_Order_OrderId", "Order").Value = value
        End Set
    End Property
    <EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
  Public Property OrderId() As Integer
        Get
            Return _orderId
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("OrderId")
                _orderId = value
                _changeTracker.EntityMemberChanged("OrderId")
            Else
                _orderId = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(EntityKeyProperty:=True, IsNullable:=False)> _
    Public Property LineItemId() As Integer
        Get
            Return _lineItemId
        End Get
        Set(ByVal value As Integer)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("LineItemId")
                _lineItemId = value
                _changeTracker.EntityMemberChanged("LineItemId")
            Else
                _lineItemId = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute()> _
    Public Property TrackingNumber() As String
        Get
            Return _trackingNumber
        End Get
        Set(ByVal value As String)
            If _trackingNumber <> value Then
                ' Validate the value before setting it.
                If value.Length > 25 Then
                    Throw New ApplicationException(String.Format( _
                            Errors.propertyNotValidString, _
                            "TrackingNumber", "25"))
                End If
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("TrackingNumber")
                    _trackingNumber = value
                    _changeTracker.EntityMemberChanged("TrackingNumber")
                Else
                    _trackingNumber = value
                End If
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Quantity() As Short
        Get
            Return _quantity
        End Get
        Set(ByVal value As Short)
            If _quantity <> value Then
                ' Validate the value before setting it.
                If value < 1 Then
                    Throw New ApplicationException(String.Format( _
                              Errors.propertyNotValidNegative, _
                              value.ToString(), "Quantity"))
                End If
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Quantity")
                    _quantity = value
                    _changeTracker.EntityMemberChanged("Quantity")
                Else
                    _quantity = value
                End If
                ' Update the line total.
                CalculateLineTotal()
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Special() As Integer
        Get
            Return _special
        End Get
        Set(ByVal value As Integer)
            If _special <> value Then
                '  Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Special")
                    _special = value
                    _changeTracker.EntityMemberChanged("Special")
                Else
                    _special = value
                End If
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Product() As Integer
        Get
            Return _product
        End Get
        Set(ByVal value As Integer)
            ' Validate the value before setting it.
            If value < 1 Then
                Throw New ApplicationException(String.Format( _
                          Errors.propertyNotValidNegative, _
                          value.ToString(), "Product"))
            End If
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("Product")
                _product = value
                _changeTracker.EntityMemberChanged("Product")
            Else
                _product = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Price() As Decimal
        Get
            Return _price
        End Get
        Set(ByVal value As Decimal)
            If _price <> value Then
                ' Validate the value before setting it.
                If value < 0 Then
                    Throw New ApplicationException(String.Format( _
                              Errors.propertyNotValidNegative, _
                              value.ToString(), "Price"))
                End If
                ' Report the change if the change tracker exists.
                If Not _changeTracker Is Nothing Then
                    _changeTracker.EntityMemberChanging("Price")
                    _price = value
                    _changeTracker.EntityMemberChanged("Price")
                Else
                    _price = value
                End If
                ' Update the line total.
                CalculateLineTotal()
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property Discount() As Decimal
        Get
            Return _discount
        End Get
        Set(ByVal value As Decimal)
            ' Validate the value before setting it.
            If value < 0 Then
                Throw New ApplicationException(String.Format( _
                          Errors.propertyNotValidNegative, _
                          value.ToString(), "Discount"))
            End If
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("Discount")
                _discount = value
                _changeTracker.EntityMemberChanged("Discount")
            Else
                _discount = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute(IsNullable:=False)> _
    Public Property RowGuid() As Guid
        Get
            Return _rowGuid
        End Get
        Set(ByVal value As Guid)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("RowGuid")
                _rowGuid = value
                _changeTracker.EntityMemberChanged("RowGuid")
            Else
                _rowGuid = value
            End If
        End Set
    End Property
    <EdmScalarPropertyAttribute()> _
   Public Property ModifiedDate() As Date
        Get
            Return _modifiedDate
        End Get
        Set(ByVal value As Date)
            ' Report the change if the change tracker exists.
            If Not _changeTracker Is Nothing Then
                _changeTracker.EntityMemberChanging("ModifiedDate")
                _modifiedDate = value
                _changeTracker.EntityMemberChanged("ModifiedDate")
            Else
                _modifiedDate = value
            End If
        End Set
    End Property
    Public ReadOnly Property Total() As Decimal
        Get
            Return _total
        End Get
    End Property
    Private Sub CalculateLineTotal()
        _total = (_quantity * (_price - _discount))
    End Sub
End Class
Public Class Errors
    Public Const propertyNotValidNegative As String = _
            "The value '{0}' for the {1} property is not valid. It cannot be a negative number or zero."
    Public Const propertyNotValidString As String = _
            "The value '{0}' for the {1} property is not valid."
End Class
using System;
using System.Data.SqlTypes;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Objects.DataClasses;
using System.Data.Metadata.Edm;
using Microsoft.Samples.Entity;

[assembly: EdmSchemaAttribute()]
[assembly: EdmRelationshipAttribute("Microsoft.Samples.Entity",
    "LineItem_Order_OrderId", "Order",
    RelationshipMultiplicity.One, typeof(Order), "LineItems",
    RelationshipMultiplicity.Many, typeof(LineItem))]
namespace Microsoft.Samples.Entity
{   
    [EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Entity", Name = "Order")]
    public class Order : IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
    {
        // Define private property variables.
        private int _orderId;
        private byte _revision;
        private DateTime _orderDate;
        private DateTime _dueDate;
        private DateTime _shipDate;
        private bool _onlineOrder;
        private byte _status;
        private int _customer;
        private int _contact;
        private int _billToAddress;
        private int _shipToAddress;
        private int _shipMethod;
        private decimal _subTotal;
        private decimal _tax;
        private decimal _freight;
        private decimal _totalDue;
        private Guid _rowGuid;
        private DateTime _modifiedDate;
        private OrderInfo _extendedInfo;

        #region ExplicitImplementation
        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;
            }
        }
        #endregion

        // Public properties of the Order object.
        [EdmScalarPropertyAttribute(EntityKeyProperty = true, IsNullable = false)]
        public int OrderId
        {
            get 
            {
                return _orderId;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("OrderId");
                    _orderId = value;
                    _changeTracker.EntityMemberChanged("OrderId");
                }
                else
                {
                    _orderId = value;
                }
            }
        }
        // Navigation property that returns a collection of line items.
        [EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Entity", "LineItem_Order_OrderId", "LineItems")]
        public EntityCollection<LineItem> LineItems
        {
            get
            {
                return ((IEntityWithRelationships)(this)).RelationshipManager.
                    GetRelatedCollection<LineItem>("Microsoft.Samples.Entity.LineItem_Order_OrderId", "LineItems");
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public byte Revision
        {
            get
            {
                return _revision;
            }
            set
            {
                if (_revision != value)
                {
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("Revision");
                        _revision = value;
                        _changeTracker.EntityMemberChanged("Revision");
                    }
                    else
                    {
                        _revision = value;
                    }
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public DateTime OrderDate 
        {
           get 
            {
                return _orderDate;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("OrderDate");
                    _orderDate = value;
                    _changeTracker.EntityMemberChanged("OrderDate");
                }
                else
                {
                    _orderDate = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public DateTime DueDate 
        {
            get 
            {
                return _dueDate;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("DueDate");
                    _dueDate = value;
                    _changeTracker.EntityMemberChanged("DueDate");
                }
                else
                {
                    _dueDate = value;
                }
            }
        }
        [EdmScalarPropertyAttribute()]
        public DateTime ShipDate
        {
            get
            {
                return _shipDate;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("ShipDate");
                    _shipDate = value;
                    _changeTracker.EntityMemberChanged("ShipDate");
                }
                else
                {
                    _shipDate = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public bool OnlineOrder
        {
            get
            {
                return _onlineOrder;
            }
            set
            {
                if (_onlineOrder != value)
                {
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("OnlineOrder");
                        _onlineOrder = value;
                        _changeTracker.EntityMemberChanged("OnlineOrder");
                    }
                    else
                    {
                        _onlineOrder = value;
                    }
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public byte Status
        {
            get 
            {
                return _status;
            }
            set
            {
                if (_status != value)
                {
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("Status");
                        _status = value;
                        _changeTracker.EntityMemberChanged("Status");
                    }
                    else
                    {
                        _status = value;
                    }
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int Customer
        {
            get
            {
                return _customer;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("Customer");
                    _customer = value;
                    _changeTracker.EntityMemberChanged("Customer");
                }
                else
                {
                    _customer = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int Contact
        {
            get
            {
                return _contact;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("Contact");
                    _contact = value;
                    _changeTracker.EntityMemberChanged("Contact");
                }
                else
                {
                    _contact = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int BillToAddress
        {
            get
            {
                return _billToAddress;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("BillToAddress");
                    _billToAddress = value;
                    _changeTracker.EntityMemberChanged("BillToAddress");
                }
                else
                {
                    _billToAddress = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int ShipToAddress
        {
            get
            {
                return _shipToAddress;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("ShipToAddress");
                    _shipToAddress = value;
                    _changeTracker.EntityMemberChanged("ShipToAddress");
                }
                else
                {
                    _shipToAddress = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int ShipMethod
        {
            get
            {
                return _shipMethod;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("ShipMethod");
                    _shipMethod = value;
                    _changeTracker.EntityMemberChanged("ShipMethod");
                }
                else
                {
                    _shipMethod = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public decimal SubTotal
        {
            get
            {
                return _subTotal;
            }
            set 
            {
                if (_subTotal != value)
                {
                    // Validate the value before setting it.
                    if (value < 0)
                    {
                        throw new ApplicationException(string.Format(
                                  Errors.propertyNotValidNegative,
                                  new string[2] { value.ToString(), "SubTotal" }));
                    }
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("SubTotal");
                        _subTotal = value;
                        _changeTracker.EntityMemberChanged("SubTotal");
                    }
                    else
                    {
                        _subTotal = value;
                    }

                    // Recalculate the order total.
                    CalculateOrderTotal();
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public decimal Tax
        {
            get
            {
                return _tax;
            }
            set
            {
                // Validate the value before setting it.
                if (value < 0)
                {
                    throw new ApplicationException(string.Format(
                              Errors.propertyNotValidNegative,
                              new string[2] { value.ToString(), "Tax" }));
                }
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("TaxAmt");
                    _tax = value;
                    _changeTracker.EntityMemberChanged("TaxAmt");
                }
                else
                {
                    _tax = value;
                }
                // Recalculate the order total.
                CalculateOrderTotal();
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public decimal Freight
        {
            get
            {
                return _freight;
            }
            set
            {
                if (_freight != value)
                {
                    // Validate the value before setting it.
                    if (value < 0)
                    {
                        throw new ApplicationException(string.Format(
                                  Errors.propertyNotValidNegative,
                                  new string[2] { value.ToString(), "Freight" }));
                    }

                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("Freight");
                        _freight = value;
                        _changeTracker.EntityMemberChanging("Freight");
                    }
                    else
                    {
                        _freight = value;
                    }

                    // Recalculate the order total.
                    CalculateOrderTotal();
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public Guid RowGuid
        {
            get
            {
                return _rowGuid;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("RowGuid");
                    _rowGuid = value;
                    _changeTracker.EntityMemberChanged("RowGuid");
                }
                else
                {
                    _rowGuid = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public DateTime ModifiedDate
        {
            get
            {
                return _modifiedDate;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("ModifiedDate");
                    _modifiedDate = value;
                    _changeTracker.EntityMemberChanged("ModifiedDate");
                }
                else
                {
                    _modifiedDate = value;
                }
            }
        }
        public decimal TotalDue
        {
            get
            {
                return _totalDue;
            }
        }
        [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);
                }
            }
        }
        private void CalculateOrderTotal()
        {
            // Update the total due as a sum of the other cost properties.
            _totalDue = _subTotal + _tax + _freight;
        }
}
    // 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);
            }
        }
    }
    [EdmComplexTypeAttribute(NamespaceName = "Microsoft.Samples.Entity", Name = "OrderInfo")]
    public partial class OrderInfo : ComplexTypeChangeTracker
    {
        private string _orderNumber;
        private string _purchaseOrder;
        private string _accountNumber;
        private string _comment;

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

        [EdmScalarPropertyAttribute(IsNullable = false)]
        public string OrderNumber
        {
            get
            {
                return _orderNumber;
            }
            set
            {
                // Validate the value before setting it.
                if (value.Length > 25)
                {
                    throw new ApplicationException(string.Format(
                              Errors.propertyNotValidString,
                              new string[3] { value, "OrderNumber", "25" }));
                }
                // Report the change if the change tracker exists.
                if (_complexChangeTracker != null)
                {
                    ReportMemberChanging("OrderNumber");
                    _orderNumber = value;
                    ReportMemberChanged("OrderNumber");
                }
                else
                {
                    _orderNumber = value;
                }
            }
        }
        [EdmScalarPropertyAttribute()]
        public string PurchaseOrder
        {
            get
            {
                return _purchaseOrder;
            }
            set
            {
                // Validate the value before setting it.
                if ((value != null) && value.Length > 25)
                {
                    throw new ApplicationException(string.Format(
                              Errors.propertyNotValidString,
                              new string[3] { value, "PurchaseOrder", "25" }));
                }
                if (_purchaseOrder != value)
                {
                    // Report the change if the change tracker exists.
                    if (_complexChangeTracker != null)
                    {
                        ReportMemberChanging("PurchaseOrder");
                        _purchaseOrder = value;
                        ReportMemberChanged("PurchaseOrder");
                    }
                    else
                    {
                        _purchaseOrder = value;
                    }
                }
            }
        }
        [EdmScalarPropertyAttribute()]
        public string AccountNumber
        {
            get
            {
                return _accountNumber;
            }
            set
            {
                // Validate the value before setting it.
                if ((value != null) && value.Length > 15)
                {
                    throw new ApplicationException(string.Format(
                              Errors.propertyNotValidString,
                              new string[3] { value, "AccountNumber", "15" }));
                }
                if (_purchaseOrder != value)
                {
                    // Report the change if the change tracker exists.
                    if (_complexChangeTracker != null)
                    {
                        ReportMemberChanging("AccountNumber");
                        _accountNumber = value;
                        ReportMemberChanged("AccountNumber");
                    }
                    else
                    {
                        _accountNumber = value;
                    }
                }
            }
        }
        [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(
                              Errors.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;
                    }
                }
            }
        }
    }

    [EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Entity", 
        Name = "LineItem")]
    public class LineItem : IEntityWithRelationships, 
        IEntityWithChangeTracker, IEntityWithKey   
    {
        // Define private property variables.
        private int _orderId;
        private int _lineItemId;
        private string _trackingNumber;
        private short _quantity;
        private int _special;
        private int _product;
        private decimal _price;
        private decimal _discount;
        private decimal _total;
        private Guid _rowGuid;
        private DateTime _modifiedDate;

        IEntityChangeTracker _changeTracker = null;
        
        // Specify the IEntityChangeTracker to use for tracking changes.
        void IEntityWithChangeTracker.SetChangeTracker(IEntityChangeTracker changeTracker)
        {
            _changeTracker = 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;
            }
        }

        // Defines a navigation property to the Order class.
        [EdmRelationshipNavigationPropertyAttribute("Microsoft.Samples.Entity", "LineItem_Order_OrderId", "Order")]
        public Order Order
        {
            get
            {
                return ((IEntityWithRelationships)(this)).RelationshipManager.
                    GetRelatedReference<Order>("LineItem_Order_OrderId", "Order").Value;
            }
            set
            {
                ((IEntityWithRelationships)(this)).RelationshipManager.
                    GetRelatedReference<Order>("LineItem_Order_OrderId", "Order").Value = value;
            }
        }
        [EdmScalarPropertyAttribute(EntityKeyProperty = true, IsNullable = false)]
        public int OrderId
        {
            get
            {
                return _orderId;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("OrderId");
                    _orderId = value;
                    _changeTracker.EntityMemberChanged("OrderId");
                }
                else
                {
                    _orderId = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(EntityKeyProperty = true, IsNullable = false)]
        public int LineItemId
        {
            get
            {
                return _lineItemId;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("LineItemId");
                    _lineItemId = value;
                    _changeTracker.EntityMemberChanged("LineItemId");
                }
                else
                {
                    _lineItemId = value;
                }
            }
        }
        [EdmScalarPropertyAttribute()]
        public string TrackingNumber
        {
            get
            {
                return _trackingNumber;
            }
            set
            {
                if (_trackingNumber != value)
                {
                    // Validate the value before setting it.
                    if (value.Length > 25)
                    {
                        throw new ApplicationException(string.Format(
                                  Errors.propertyNotValidString,
                                  new string[3] {value,"TrackingNumber", "25"}));
                    }
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("TrackingNumber");
                        _trackingNumber = value;
                        _changeTracker.EntityMemberChanged("TrackingNumber");
                    }
                    else
                    {
                        _trackingNumber = value;
                    }
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public short Quantity
        {
            get
            {
                return _quantity;
            }
            set
            {
                if (_quantity != value)
                {
                    // Validate the value before setting it.
                    if (value < 1)
                    {
                        throw new ApplicationException(string.Format(
                                  Errors.propertyNotValidNegative,
                                  new string[2] { value.ToString(), "Quantity" }));
                    }
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("Quantity");
                        _quantity = value;
                        _changeTracker.EntityMemberChanged("Quantity");
                    }
                    else
                    {
                        _quantity = value;
                    }
 
                    // Update the line total.
                    CalculateLineTotal();
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int Special
        {
            get
            {
                return _special;
            }
            set
            {
                if (_special != value)
                {
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("Special");
                        _special = value;
                        _changeTracker.EntityMemberChanged("Special");
                    }
                    else
                    {
                        _special = value;
                    }
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public int Product
        {
            get
            {
                return _product;
            }
            set
            {
                // Validate the value before setting it.
                if (value < 1)
                {
                    throw new ApplicationException(string.Format(
                              Errors.propertyNotValidNegative, 
                              new string[2] { value.ToString(), "Product" }));
                }
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("Product");
                    _product = value;
                    _changeTracker.EntityMemberChanged("Product");
                }
                else
                {
                    _product = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)] 
        public decimal Price
        {
            get
            {
                return _price;
            }
            set
            {
                if (_price != value)
                {
                    // Validate the value before setting it.
                    if (value < 0)
                    {
                        throw new ApplicationException(string.Format(
                                  Errors.propertyNotValidNegative,
                                  new string[2] { value.ToString(), "Price" }));
                    }
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("Price");
                        _price = value;
                        _changeTracker.EntityMemberChanged("Price");
                    }
                    else 
                    { 
                        _price = value;
                    }

                    // Update the line total.
                    CalculateLineTotal();
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public decimal Discount
        {
            get
            {
                return _discount;
            }
            set
            {
                // Validate the value before setting it.
                if (value < 0)
                {
                    throw new ApplicationException(string.Format(
                              Errors.propertyNotValidNegative,
                              new string[2] { value.ToString(), "Discount" }));
                }
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("Discount");
                    _discount = value;
                    _changeTracker.EntityMemberChanged("Discount");
                }
                else
                {
                    _discount = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public Guid RowGuid
        {
            get
            {
                return _rowGuid;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("RowGuid");
                    _rowGuid = value;
                    _changeTracker.EntityMemberChanged("RowGuid");
                }
                else
                {
                    _rowGuid = value;
                }
            }
        }
        [EdmScalarPropertyAttribute(IsNullable = false)]
        public DateTime ModifiedDate
        {
            get
            {
                return _modifiedDate;
            }
            set
            {
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging("ModifiedDate");
                    _modifiedDate = value;
                    _changeTracker.EntityMemberChanged("ModifiedDate");
                }
                else
                {
                    _modifiedDate = value;
                }
            }
        }
        public decimal Total
        {
            get
            {
                return _total;
            }
        }
        private void CalculateLineTotal()
        {
            _total = (_quantity * (_price - _discount)); 
        }
    }
    public class Errors
    {
        public const string propertyNotValidNegative =
            @"The value '{0}' for the {1} property is not valid. It cannot be a negative number or zero.";
        public const string propertyNotValidString =
            @"The value '{0}' for the {1} property is not valid.";
    }
}

See Also

Tasks

How to: Customize an Entity Data Model to Work with Custom Objects (Entity Framework)

Other Resources

Working with Custom Objects (Entity Framework Tasks)