当您将自定义数据类用于 实体数据模型 (EDM) 时,这些类必须实现以下自定义数据类接口:
- IEntityWithChangeTracker。启用更改跟踪。 
- IEntityWithKey。可选。公开实体键。 
- IEntityWithRelationships。对于具有关联的实体,这是必需的。 
有关更多信息,请参见实现自定义数据类接口(实体框架)。还必须应用 EDM 属性 (Attribute),这些属性将自定义类和属性 (Property) 映射到在概念架构定义语言 (CSDL) 文件中定义的实体。有关更多信息,请参见如何:将自定义对象映射到实体(实体框架)。
您还可以从 EntityObject 继承,而不是直接实现数据类接口。这是将自定义数据类用于 EDM 的推荐方法。有关更多信息,请参见自定义对象(实体框架) 和如何:从 EntityObject 和 ComplexObject 基类继承(实体框架)。
实现自定义数据类接口
- 修改每个自定义数据类的定义,以便它实现 IEntityWithChangeTracker、IEntityWithKey 和 IEntityWithRelationships 接口,如以下示例所示: - <EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="Order")> _ Public Class Order Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey- [EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Edm", Name = "Order")] public class Order : IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
- (可选)在每个自定义数据类中显式实现 EntityKey 属性,如以下示例所示: - 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- EntityKey _entityKey = null; // Define the EntityKey property for the class. EntityKey IEntityWithKey.EntityKey { get { return _entityKey; } set { // Set the EntityKey property, if it is not set. // Report the change if the change tracker exists. if (_changeTracker != null) { _changeTracker.EntityMemberChanging(StructuralObject.EntityKeyPropertyName); _entityKey = value; _changeTracker.EntityMemberChanged(StructuralObject.EntityKeyPropertyName); } else { _entityKey = value; } } }
- 在每个自定义数据类中显式实现 SetChangeTracker 方法,如以下示例所示: - 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); } }- 若要将数据属性中的更改报告给对象服务,此方法是必需的。 
- 对于 IEntityWithRelationships,显式实现 RelationshipManager 属性,如以下示例所示: - 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; } }
- 在每个数据类的可设置的标量属性中,在设置 EntityMemberChanging 属性的值之前添加对此属性的调用,并在设置 EntityMemberChanged 属性之后添加对此属性的调用。下面的示例对此进行了演示: - <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; } } } }
- 在每个数据类的可设置的复杂属性中,在设置 EntityComplexMemberChanging 属性的值之前添加对此属性的调用,并在设置 EntityComplexMemberChanged 属性之后添加对此属性的调用。 
示例
本示例说明自定义数据类 Order 和 LineItem 以及复杂类型 OrderInfo。这些自定义类映射到 AdventureWorks 数据库中的 SalesOrderHeader 和 SalesOrderDetail 表。这两个实体类同时实现所有这三个自定义数据类接口。OrderInfo 复杂类型类演示了建议的更改跟踪实现。
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
Imports Microsoft.Samples.Edm
<Assembly: EdmSchemaAttribute()> 
<Assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm", _
    "FK_LineItem_Order_OrderId", "Order", _
    RelationshipMultiplicity.One, GetType(Order), "LineItem", _
    RelationshipMultiplicity.Many, GetType(LineItem))> 
Namespace Microsoft.Samples.Edm
    <EdmEntityTypeAttribute(NamespaceName:="Microsoft.Samples.Edm", Name:="Order")> _
    Public Class Order
        Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
        ' Define private property variables.
        Private _orderId As Integer
        Private _orderDate As DateTime
        Private _dueDate As DateTime
        Private _shipDate As DateTime
        Private _status As Byte
        Private _customer As Integer
        Private _subTotal As Decimal
        Private _tax As Decimal
        Private _freight As Decimal
        Private _totalDue As Decimal
        Private _extendedInfo As OrderInfo
#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, 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
#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.Edm", "FK_LineItem_Order_OrderId", "LineItem")> _
        Public ReadOnly Property LineItem() As EntityCollection(Of LineItem)
            Get
                Return CType(Me, IEntityWithRelationships).RelationshipManager.GetRelatedCollection(Of LineItem) _
                ("FK_LineItem_Order_OrderId", "LineItem")
            End Get
        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")
                    _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")
                    _changeTracker.EntityMemberChanged("ShipDate")
                Else
                    _shipDate = value
                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 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( _
                                  My.Resources.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 TaxAmt() 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( _
                              My.Resources.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( _
                                  My.Resources.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
        <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.Edm", 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( _
                        My.Resources.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( _
                              My.Resources.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( _
                              My.Resources.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( _
                              My.Resources.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.Edm", Name:="LineItem")> _
Public Class LineItem
        Implements IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
        ' Define private property variables.
        Dim _lineItemId As Integer
        Dim _trackingNumber As String
        Dim _quantity As Short
        Dim _product As Integer
        Dim _price As Decimal
        Dim _discount As Decimal
        Dim _total As Decimal
        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.
                ' Changing an existing value will cause an exception.
                If _entityKey Is Nothing Then
                    ' 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 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.Edm", _
                "FK_LineItem_Order_OrderId", "Order")> _
        Public Property Order() As Order
            Get
                Return CType(Me,  _
                IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of Order) _
                ("FK_LineItem_Order_OrderId", "Order").Value
            End Get
            Set(ByVal value As Order)
                CType(Me,  _
                IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of Order) _
                ("FK_LineItem_Order_OrderId", "Order").Value = value
            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( _
                                My.Resources.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( _
                                  My.Resources.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 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( _
                              My.Resources.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( _
                                  My.Resources.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( _
                              My.Resources.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
        Public ReadOnly Property Total() As Decimal
            Get
                Return _total
            End Get
        End Property
        Private Sub CalculateLineTotal()
            _total = (_quantity * (_price - _discount))
        End Sub
    End Class
End Namespace
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.Edm;
//using Microsoft.Samples.Edm;
[assembly: EdmSchemaAttribute()]
[assembly: EdmRelationshipAttribute("Microsoft.Samples.Edm",
    "FK_LineItem_Order_OrderId", "Order",
    RelationshipMultiplicity.One, typeof(Order), "LineItem",
    RelationshipMultiplicity.Many, typeof(LineItem))]
namespace Microsoft.Samples.Edm
{   
    [EdmEntityTypeAttribute(NamespaceName = "Microsoft.Samples.Edm", Name = "Order")]
    public class Order : IEntityWithRelationships, IEntityWithChangeTracker, IEntityWithKey
    {
        // Define private property variables.
        private int _orderId;
        private DateTime _orderDate;
        private DateTime _dueDate;
        private DateTime _shipDate;
        private byte _status;
        private int _customer;
        private decimal _subTotal;
        private decimal _tax;
        private decimal _freight;
        private decimal _totalDue;
        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, if it is not set.
                // Report the change if the change tracker exists.
                if (_changeTracker != null)
                {
                    _changeTracker.EntityMemberChanging(StructuralObject.EntityKeyPropertyName);
                    _entityKey = value;
                    _changeTracker.EntityMemberChanged(StructuralObject.EntityKeyPropertyName);
                }
                else
                {
                    _entityKey = value;
                }
            }
        }
        RelationshipManager _relationships = null;
        // Define a relationship manager for the class.
        RelationshipManager IEntityWithRelationships.RelationshipManager
        {
            get
            {
                if (null == _relationships)
                    _relationships = RelationshipManager.Create(this);
                return _relationships;
            }
        }
        #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.Edm", "FK_LineItem_Order_OrderId", "LineItem")]
        public System.Data.Objects.DataClasses.EntityCollection<LineItem> LineItem
        {
            get
            {
                return ((IEntityWithRelationships)(this)).RelationshipManager.
                    GetRelatedCollection<LineItem>("FK_LineItem_Order_OrderId", "LineItem");
            }
        }
        [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 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 decimal SubTotal
        {
            get
            {
                return _subTotal;
            }
            set 
            {
                if (_subTotal != value)
                {
                    // Validate the value before setting it.
                    if (value < 0)
                    {
                        throw new ApplicationException(string.Format(
                                  Properties.Resources.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 TaxAmt
        {
            get
            {
                return _tax;
            }
            set
            {
                // Validate the value before setting it.
                if (value < 0)
                {
                    throw new ApplicationException(string.Format(
                              Properties.Resources.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(
                                  Properties.Resources.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();
                }
            }
        }
        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.Edm", 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(
                              Properties.Resources.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(
                              Properties.Resources.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(
                              Properties.Resources.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(
                              Properties.Resources.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.Edm", 
        Name = "LineItem")]
    public class LineItem : IEntityWithRelationships, 
        IEntityWithChangeTracker, IEntityWithKey   
    {
        // Define private property variables.
        int _lineItemId; 
        string _trackingNumber;
        short _quantity;
        int _product;
        decimal _price;
        decimal _discount;
        decimal _total;
        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, if it is not set.
                // Changing an existing value will cause an exception.
                if (_entityKey == null)
                {
                    // 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.Edm", "FK_LineItem_Order_OrderId", "Order")]
        public Order Order
        {
            get
            {
                return ((IEntityWithRelationships)(this)).RelationshipManager.
                    GetRelatedReference<Order>("FK_LineItem_Order_OrderId", "Order").Value;
            }
            set
            {
                ((IEntityWithRelationships)(this)).RelationshipManager.
                    GetRelatedReference<Order>("FK_LineItem_Order_OrderId", "Order").Value = 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(
                                  Properties.Resources.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(
                                  Properties.Resources.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 Product
        {
            get
            {
                return _product;
            }
            set
            {
                // Validate the value before setting it.
                if (value < 1)
                {
                    throw new ApplicationException(string.Format(
                              Properties.Resources.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(
                                  Properties.Resources.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(
                              Properties.Resources.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;
                }
            }
        }
        
        public decimal Total
        {
            get
            {
                return _total;
            }
        }
        private void CalculateLineTotal()
        {
            _total = (_quantity * (_price - _discount)); 
        }
    }
}