예제 #1
0
        /// <summary>
        /// Submits the changes to the database: executes Insert, Update and Delete queries based on the changes found in the tracked entities.
        /// </summary>
        /// <param name="failureMode">The failure mode.</param>
        internal void SubmitChanges(ConflictMode failureMode)
        {
            this.TrackUntrackedObjects();
            // Must apply inferred deletions only after any untracked objects
            // are tracked
            this.ApplyInferredDeletions();
            this.BuildEdgeMaps();

            var list = this.GetOrderedList();

            ValidateAll(list);

            int numUpdatesAttempted = 0;
            ChangeConflictSession       conflictSession    = new ChangeConflictSession(this._context);
            List <ObjectChangeConflict> conflicts          = new List <ObjectChangeConflict>();
            List <TrackedObject>        deletedItems       = new List <TrackedObject>();
            List <TrackedObject>        insertedItems      = new List <TrackedObject>();
            List <TrackedObject>        syncDependentItems = new List <TrackedObject>();

            foreach (TrackedObject item in list)
            {
                try
                {
                    if (item.IsNew)
                    {
                        if (item.SynchDependentData())
                        {
                            syncDependentItems.Add(item);
                        }
                        _changeDirector.Insert(item);
                        // store all inserted items for post processing
                        insertedItems.Add(item);
                    }
                    else if (item.IsDeleted)
                    {
                        // Delete returns 1 if the delete was successfull, 0 if the row exists
                        // but wasn't deleted due to an OC conflict, or -1 if the row was
                        // deleted by another context (no OC conflict in this case)
                        numUpdatesAttempted++;
                        int ret = _changeDirector.Delete(item);
                        if (ret == 0)
                        {
                            conflicts.Add(new ObjectChangeConflict(conflictSession, item, false));
                        }
                        else
                        {
                            // store all deleted items for post processing
                            deletedItems.Add(item);
                        }
                    }
                    else if (item.IsPossiblyModified)
                    {
                        if (item.SynchDependentData())
                        {
                            syncDependentItems.Add(item);
                        }
                        if (item.IsModified)
                        {
                            CheckForInvalidChanges(item);
                            numUpdatesAttempted++;
                            if (_changeDirector.Update(item) <= 0)
                            {
                                conflicts.Add(new ObjectChangeConflict(conflictSession, item));
                            }
                        }
                    }
                }
                catch (ChangeConflictException)
                {
                    conflicts.Add(new ObjectChangeConflict(conflictSession, item));
                }
                if (conflicts.Count > 0 && failureMode == ConflictMode.FailOnFirstConflict)
                {
                    break;
                }
            }

            // if we have accumulated any failed updates, throw the exception now
            if (conflicts.Count > 0)
            {
                // First we need to rollback any value that have already been auto-[....]'d, since the values are no longer valid on the server
                _changeDirector.RollbackAutoSync();
                // Also rollback any dependent items that were [....]'d, since their parent values may have been rolled back
                foreach (TrackedObject syncDependentItem in syncDependentItems)
                {
                    Debug.Assert(syncDependentItem.IsNew || syncDependentItem.IsPossiblyModified, "SynchDependent data should only be rolled back for new and modified objects.");
                    syncDependentItem.SynchDependentData();
                }
                this._context.ChangeConflicts.Fill(conflicts);
                throw CreateChangeConflictException(numUpdatesAttempted, conflicts.Count);
            }
            else
            {
                // No conflicts occurred, so we don't need to save the rollback values anymore
                _changeDirector.ClearAutoSyncRollback();
            }

            // Only after all updates have been sucessfully processed do we want to make
            // post processing modifications to the objects and/or cache state.
            PostProcessUpdates(insertedItems, deletedItems);
        }
        internal void SubmitChanges(ConflictMode failureMode) {
            this.TrackUntrackedObjects();
            // Must apply inferred deletions only after any untracked objects
            // are tracked
            this.ApplyInferredDeletions();
            this.BuildEdgeMaps();

            var list = this.GetOrderedList();

            ValidateAll(list);

            int numUpdatesAttempted = 0;
            ChangeConflictSession conflictSession = new ChangeConflictSession(this.context);
            List<ObjectChangeConflict> conflicts = new List<ObjectChangeConflict>();
            List<TrackedObject> deletedItems = new List<TrackedObject>();
            List<TrackedObject> insertedItems = new List<TrackedObject>();
            List<TrackedObject> syncDependentItems = new List<TrackedObject>();
            
            foreach (TrackedObject item in list) {
                try {
                    if (item.IsNew) {
                        if (item.SynchDependentData()) {
                            syncDependentItems.Add(item);
                        }
                        changeDirector.Insert(item);
                        // store all inserted items for post processing
                        insertedItems.Add(item);
                    }
                    else if (item.IsDeleted) {
                        // Delete returns 1 if the delete was successfull, 0 if the row exists
                        // but wasn't deleted due to an OC conflict, or -1 if the row was
                        // deleted by another context (no OC conflict in this case)
                        numUpdatesAttempted++;
                        int ret = changeDirector.Delete(item);
                        if (ret == 0) {
                            conflicts.Add(new ObjectChangeConflict(conflictSession, item, false));
                        }
                        else {
                            // store all deleted items for post processing
                            deletedItems.Add(item);
                        }
                    }
                    else if (item.IsPossiblyModified) {
                        if (item.SynchDependentData()) {
                            syncDependentItems.Add(item);
                        }
                        if (item.IsModified) {
                            CheckForInvalidChanges(item);
                            numUpdatesAttempted++;
                            if (changeDirector.Update(item) <= 0) {
                                conflicts.Add(new ObjectChangeConflict(conflictSession, item));
                            }
                        }
                    }
                }
                catch (ChangeConflictException) {
                    conflicts.Add(new ObjectChangeConflict(conflictSession, item));
                }
                if (conflicts.Count > 0 && failureMode == ConflictMode.FailOnFirstConflict) {
                    break;
                }
            }

            // if we have accumulated any failed updates, throw the exception now
            if (conflicts.Count > 0) {
                // First we need to rollback any value that have already been auto-[....]'d, since the values are no longer valid on the server
                changeDirector.RollbackAutoSync();
                // Also rollback any dependent items that were [....]'d, since their parent values may have been rolled back
                foreach (TrackedObject syncDependentItem in syncDependentItems) {
                    Debug.Assert(syncDependentItem.IsNew || syncDependentItem.IsPossiblyModified, "SynchDependent data should only be rolled back for new and modified objects.");
                    syncDependentItem.SynchDependentData();
                }
                this.context.ChangeConflicts.Fill(conflicts);
                throw CreateChangeConflictException(numUpdatesAttempted, conflicts.Count);
            }
            else {
                // No conflicts occurred, so we don't need to save the rollback values anymore
                changeDirector.ClearAutoSyncRollback();
            }

            // Only after all updates have been sucessfully processed do we want to make
            // post processing modifications to the objects and/or cache state.
            PostProcessUpdates(insertedItems, deletedItems);
        }
예제 #3
0
 internal ObjectChangeConflict(ChangeConflictSession session, TrackedObject trackedObject, bool isDeleted)
     : this(session, trackedObject)
 {
     this.isDeleted = isDeleted;
 }
예제 #4
0
 internal ObjectChangeConflict(ChangeConflictSession session, TrackedObject trackedObject)
 {
     Session       = session;
     TrackedObject = trackedObject;
     Original      = trackedObject.CreateDataCopy(trackedObject.Original);
 }
예제 #5
0
        internal void SubmitChanges(ConflictMode failureMode)
        {
            TrackUntrackedObjects();
            ApplyInferredDeletions();
            BuildEdgeMaps();
            var orderedList = GetOrderedList();

            ValidateAll(orderedList);
            var num     = 0;
            var session = new ChangeConflictSession(context);
            var list    = new List <ObjectChangeConflict>();
            var list2   = new List <TrackedObject>();
            var list3   = new List <TrackedObject>();
            var list4   = new List <TrackedObject>();

            foreach (var item in orderedList)
            {
                try {
                    if (item.IsNew)
                    {
                        if (item.SynchDependentData())
                        {
                            list4.Add(item);
                        }
                        changeDirector.Insert(item);
                        list3.Add(item);
                    }
                    else if (item.IsDeleted)
                    {
                        num++;
                        if (changeDirector.Delete(item) == 0)
                        {
                            list.Add(new ObjectChangeConflict(session, item, false));
                        }
                        else
                        {
                            list2.Add(item);
                        }
                    }
                    else if (item.IsPossiblyModified)
                    {
                        if (item.SynchDependentData())
                        {
                            list4.Add(item);
                        }
                        if (item.IsModified)
                        {
                            CheckForInvalidChanges(item);
                            num++;
                            if (changeDirector.Update(item) <= 0)
                            {
                                list.Add(new ObjectChangeConflict(session, item));
                            }
                        }
                    }
                } catch (ChangeConflictException) {
                    list.Add(new ObjectChangeConflict(session, item));
                }
                if (list.Count > 0 && failureMode == ConflictMode.FailOnFirstConflict)
                {
                    break;
                }
            }
            if (list.Count > 0)
            {
                changeDirector.RollbackAutoSync();
                foreach (var item2 in list4)
                {
                    item2.SynchDependentData();
                }
                context.ChangeConflicts.Fill(list);
                throw CreateChangeConflictException(num, list.Count);
            }
            changeDirector.ClearAutoSyncRollback();
            PostProcessUpdates(list3, list2);
        }
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="session">The session in which the conflicts occurred.</param>
		/// <param name="trackedObject">The tracked item in conflict.</param>
		/// <param name="isDeleted">True if the item in conflict no longer exists in the database.</param>
		internal ObjectChangeConflict(ChangeConflictSession session, TrackedObject trackedObject, bool isDeleted)
			: this(session, trackedObject)
		{
			this.isDeleted = isDeleted;
		}
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="session">The session in which the conflicts occurred.</param>
		/// <param name="trackedObject">The tracked item in conflict.</param>
		internal ObjectChangeConflict(ChangeConflictSession session, TrackedObject trackedObject)
		{
			this.session = session;
			this.trackedObject = trackedObject;
			this.original = trackedObject.CreateDataCopy(trackedObject.Original);
		}