Exemplo n.º 1
0
        /// <summary>
        /// Recursively enable or disable tracking on trackable entities in an object graph.
        /// </summary>
        /// <param name="item">Trackable object</param>
        /// <param name="enableTracking">Enable or disable change-tracking</param>
        /// <param name="visitationHelper">Circular reference checking helper</param>
        /// <param name="oneToManyOnly">True if tracking should be set only for OneToMany relations</param>
        public static void SetTracking(this ITrackable item, bool enableTracking,
                                       ObjectVisitationHelper visitationHelper = null, bool oneToManyOnly = false)
        {
            // Iterator entity properties
            foreach (var navProp in item.GetNavigationProperties())
            {
                // Skip if 1-M only
                if (!oneToManyOnly)
                {
                    // Set tracking on 1-1 and M-1 properties
                    foreach (var refProp in navProp.AsReferenceProperty())
                    {
                        // Get ref prop change tracker
                        ITrackingCollection refChangeTracker = item.GetRefPropertyChangeTracker(refProp.Property.Name);
                        if (refChangeTracker != null)
                        {
                            // Set tracking on ref prop change tracker
                            refChangeTracker.SetTracking(enableTracking, visitationHelper, oneToManyOnly);
                        }
                    }
                }

                // Set tracking on 1-M and M-M properties (if not 1-M only)
                foreach (var colProp in navProp.AsCollectionProperty <ITrackingCollection>())
                {
                    bool isOneToMany = !IsManyToManyChildCollection(colProp.EntityCollection);
                    if (!oneToManyOnly || isOneToMany)
                    {
                        colProp.EntityCollection.SetTracking(enableTracking, visitationHelper, oneToManyOnly);
                    }
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Recursively enable or disable tracking on trackable entities in an object graph.
        /// </summary>
        /// <param name="item">Trackable object</param>
        /// <param name="enableTracking">Enable or disable change-tracking</param>
        /// <param name="visitationHelper">Circular reference checking helper</param>
        public static void SetTracking(this ITrackable item,
                                       bool enableTracking, ObjectVisitationHelper visitationHelper = null)
        {
            // Iterator entity properties
            foreach (var navProp in item.GetNavigationProperties())
            {
                // Set tracking on 1-1 and M-1 properties
                foreach (var refProp in navProp.AsReferenceProperty())
                {
                    // Get ref prop change tracker
                    ITrackingCollection refChangeTracker = item.GetRefPropertyChangeTracker(refProp.Property.Name);
                    if (refChangeTracker != null)
                    {
                        // Set tracking on ref prop change tracker
                        refChangeTracker.SetTracking(enableTracking, visitationHelper);
                    }
                }

                // Set tracking on 1-M and M-M properties
                foreach (var colProp in navProp.AsCollectionProperty <ITrackingCollection>())
                {
                    colProp.EntityCollection.SetTracking(enableTracking, visitationHelper);
                }
            }
        }
            /// <summary>
            /// Get entities that have been added, modified or deleted, including trackable
            /// reference and child entities.
            /// </summary>
            /// <param name="items">Collection of ITrackable objects</param>
            /// <returns>Collection containing only added, modified or deleted entities</returns>
            private IEnumerable <ITrackable> GetChanges(IEnumerable <ITrackable> items)
            {
                // Prevent endless recursion by collection
                if (!visitationHelper.TryVisit(items))
                {
                    yield break;
                }

                // Prevent endless recursion by item
                items = items.Where(i => visitationHelper.TryVisit(i)).ToList();

                // Iterate items in change-tracking collection
                foreach (ITrackable item in items)
                {
                    // Downstream changes flag
                    bool hasDownstreamChanges = false;

                    // Iterate entity properties
                    foreach (var navProp in item.GetNavigationProperties())
                    {
                        // Process 1-1 and M-1 properties
                        foreach (var refProp in navProp.AsReferenceProperty())
                        {
                            ITrackable trackableRef = refProp.EntityReference;

                            // if already visited and unchanged, set to null
                            if (visitationHelper.IsVisited(trackableRef))
                            {
                                if ((trackableRef.TrackingState == TrackingState.Unchanged ||
                                     trackableRef.TrackingState == TrackingState.Deleted))
                                {
                                    EntityInfo(item).RefNavPropUnchanged.Add(refProp.Property);
                                }
                                continue;
                            }

                            // Get changed ref prop
                            ITrackingCollection refChangeTracker = trackableRef.GetRefPropertyChangeTracker(refProp.Property.Name);//item.GetRefPropertyChangeTracker(refProp.Property.Name);
                            if (refChangeTracker != null)
                            {
                                hasDownstreamChanges = HasDownstreamChanges(refChangeTracker, trackableRef, item, refProp, hasDownstreamChanges);
                            }
                        }

                        // Process 1-M and M-M properties
                        foreach (var colProp in navProp.AsCollectionProperty <IList>())
                        {
                            // Get changes on child collection
                            var trackingItems = colProp.EntityCollection;
                            if (trackingItems.Count > 0)
                            {
                                // Continue recursion if trackable hasn't been visited
                                if (!visitationHelper.IsVisited(trackingItems))
                                {
                                    hasDownstreamChanges = GetChangesOnChildCollection(trackingItems, hasDownstreamChanges, item, colProp);
                                }
                            }
                        }
                    }

                    // Return item if it has changes
                    if (hasDownstreamChanges || item.TrackingState != TrackingState.Unchanged)
                    {
                        yield return(item);
                    }
                }
            }