LinqConnect Documentation
In This Topic
    Modifying Navigation Properties
    In This Topic
    Modifying Navigation Properties
    LinqConnect Documentation
    Modifying Navigation Properties
    [email protected]

    On the database side, relations between records are stored as foreign keys. On the application side, in addition to fields, entity associations are implemented by the help of navigation properties, which actually are references to other entities. This topic describes the differences between change tracking of "simple" entity properties and navigation properties.

    These differences mostly apply to the collection navigation properties. Navigation properties, which refer to a single entity, can be simply stored in the entity copy (which stores the original entity state). Original and current references can be easily compared in the same way as simple entity properties.

    Note:
    Actually this can be not so easy: simple entity properties are just usual value types, and entity references are of reference types. Generally, when comparing reference types, equal (by content) objects can have different references. However, LinqConnect caches objects (see Object Identity), thus this is not the case.

    When tracking navigation properties of many sides of associations, the differences became more important. These navigation properties are collections, so it is necessary to track not just the value of such property (reference to a collection), but also the entity references in this collection. So, it is necessary to make a copy of the dependent entity list and compare the original and current lists element-by-element (for each association with a many side of each entity, attached to the context). LinqConnect does this if necessary, however it's obvious that such operations reduce performance. That's why it's better to use our EntitySet type for ollection navigation properties because this type supports notifications on changes in its content.

    EntitySets and Change Tracking

    Generic class EntitySet<TEntity> has two delegates of the Action<TEntity> type: onAdd and onRemove. These delegates are called when adding or removing an entity from the EntitySet respectively. They can be passed to the public constructor of EntitySet, so when creating a PropertyChanging event, we can notify the context about navigation property change without examining all the collections in all of the attached entities. The notifications are done by the following code, generated by the 'LinqConnect' template (the sample is generated for the Productcategory class and its Products navigation property, irrelevant fragments of code were omitted):


    C#csharpCopy Code
    public partial class Productcategory : INotifyPropertyChanging, INotifyPropertyChanged    
    {
     
        ...
     
        private EntitySet<Product> _Products;
     
        ...
     
        public Productcategory()
        {
            this._Products = 
                new EntitySet<Product>(
                    new Action<Product>(this.attach_Products), 
                    new Action<Product>(this.detach_Products)
                );
    
            ...
    
        }
     
        ...
    
        public EntitySet<Product> Products
        {
            get { return this._Products; }
            set { this._Products.Assign(value);  }
        }
     
        ...
     
        protected virtual void SendPropertyChanging()
        {
            if (this.PropertyChanging != null)
                this.PropertyChanging(this, emptyChangingEventArgs);
        }
     
        ...
     
        private void attach_Products(Product entity)
        {
            this.SendPropertyChanging("Products");
            ...
        }
     
        private void detach_Products(Product entity)
        {
            this.SendPropertyChanging("Products");
            ...
        }
    }
    Visual BasicCopy Code
    Public Partial Class Productcategory
     
        ...
     
        Private _Products As EntitySet(Of Product)
     
        ...
     
        Public Sub New()
            Me._Products = New EntitySet(Of Product)( _ 
                AddressOf Me.attach_Products, _
                AddressOf Me.detach_Products _ 
            ) 
    
            ...
     
        End Sub
     
        ...
     
        Public Property Products As EntitySet(Of Product)
            Get
                Return Me._Products
            End Get
            Set
                Me._Products.Assign(value)
            End Set
        End Property
     
        Public Event PropertyChanging As PropertyChangingEventHandler _
            Implements System.ComponentModel.INotifyPropertyChanging.PropertyChanging
     
        Public Event PropertyChanged As PropertyChangedEventHandler _
            Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
     
        Protected Overridable Sub SendPropertyChanging()
            If (Not Me.PropertyChangingEvent Is Nothing) Then
                RaiseEvent PropertyChanging(Me, emptyChangingEventArgs)
            End If
        End Sub
     
        ...
     
        Private Sub attach_Products(entity As Product)
            Me.SendPropertyChanging("Products")
            ...
        End Sub
     
        Private Sub detach_Products(entity As Product)
            Me.SendPropertyChanging("Products")
            ...
        End Sub
    End Class

    The attach_Products and detach_Products methods are created. These methods are passed to the Products constructor. As it was already mentioned, this means that adding/removing Products collection elements will trigger these methods.

    As for tracking, attach_Products/detach_Products methods raises SendPropertyChanging. Either method notifies runtime about which property of which entity is being modified. It allows to limit the number of collectionsto check when submitting changes.

    To speed up this process, Entity Set stores the collections of added and deleted entities. So, there is no need to copy or enumerate the list of dependent entities - EntitySet knows what was added or deleted.