Exemple #1
0
        /// <summary>
        ///     Gets the selection set that corresponds to the conflict class.
        /// </summary>
        /// <param name="conflictClass">The conflict class.</param>
        /// <param name="conflictType">Type of the conflict.</param>
        /// <returns>Returns the <see cref="ISelectionSet" /> representing the set of conflicts.</returns>
        protected ISelectionSet GetConflictSet(IConflictClass conflictClass, TableConflictType conflictType)
        {
            if (conflictClass == null)
            {
                throw new ArgumentNullException("conflictClass");
            }

            ISelectionSet set = null;

            switch (conflictType)
            {
            case TableConflictType.DeleteUpdates:
                set = conflictClass.DeleteUpdates;
                break;

            case TableConflictType.UpdateDeletes:
                set = conflictClass.UpdateDeletes;
                break;

            default:
                set = conflictClass.UpdateUpdates;
                break;
            }

            return(set);
        }
Exemple #2
0
        /// <summary>
        ///     The main method for resolving conflicts for all of the rows for the <paramref name="conflictClass" />
        ///     that have the conflict type matching the <paramref name="conflictType" /> enumeration.
        /// </summary>
        /// <param name="conflictClass">The class that has the conflicts.</param>
        /// <param name="currentTable">The table in the current version.</param>
        /// <param name="preReconcileTable">The table prior to reconciliation.</param>
        /// <param name="reconcileTable">The table that the current version is reconciling against.</param>
        /// <param name="commonAncestorTable">The common ancestor table of this version and the reconcile version.</param>
        /// <param name="conflictType">Type of the conflict.</param>
        /// <param name="filters">The conflict filters.</param>
        /// <returns>
        ///     A boolean indicating if all conflicts have been resolved.
        /// </returns>
        protected bool ResolveConflicts(IConflictClass conflictClass, ITable currentTable, ITable preReconcileTable, ITable reconcileTable, ITable commonAncestorTable, TableConflictType conflictType, IEnumerable <IConflictFilter> filters)
        {
            ISelectionSet set = this.GetConflictSet(conflictClass, conflictType);

            if (set == null)
            {
                return(false);
            }

            string tableName = ((IDataset)conflictClass).Name;

            Log.Info("Resolving the '{0}' type of conflicts for {1} row(s) in the {2} class.", conflictType, set.Count, tableName);

            var list = filters.Where(o => o.CanResolve(conflictType, conflictClass)).ToArray();

            if (list.Length == 0)
            {
                Log.Warn("There's no conflict filters available that support the conflict type of {0} for the {1} class.", conflictType, tableName);
                return(false);
            }

            FieldsEqualityComparer equalityComparer = new FieldsEqualityComparer();
            List <IConflictRow>    rows             = new List <IConflictRow>();
            IEnumIDs enumIDs = set.IDs;

            enumIDs.Reset();

            int oid;

            while ((oid = enumIDs.Next()) != -1)
            {
                using (ComReleaser cr = new ComReleaser())
                {
                    // The row from the edited (current) version.
                    IRow currentRow = currentTable.Fetch(oid);
                    cr.ManageLifetime(currentRow);

                    // The row from the edit (child) version.
                    IRow preReconcileRow = preReconcileTable.Fetch(oid);
                    cr.ManageLifetime(preReconcileRow);

                    // The row from the target (parent) version.
                    IRow reconcileRow = reconcileTable.Fetch(oid);
                    cr.ManageLifetime(reconcileRow);

                    // The row from the common ancestor (as is in the database) version.
                    IRow commonAncestorRow = commonAncestorTable.Fetch(oid);
                    cr.ManageLifetime(commonAncestorRow);

                    // Determine the row conflict type at a granular level.
                    RowConflictType rowConflictType = this.GetRowConflictType(preReconcileRow, reconcileRow, commonAncestorRow, equalityComparer);
                    Log.Info("Resolving the '{0}' conflict type for the {1} row using {2} filter(s).", rowConflictType, oid, list.Length);

                    // Use the filters to "attempt" to resolve the conflicts.
                    IConflictRow conflictRow = new ConflictRow(oid, tableName, rowConflictType);
                    foreach (var filter in list.OrderBy(o => o.Priority))
                    {
                        conflictRow.Resolution = filter.Resolve(conflictRow, conflictClass, currentRow, preReconcileRow, reconcileRow, commonAncestorRow, this.ChildWins, this.ColumnLevel);
                    }

                    Log.Info("The resolution of the {0} row has been marked as '{1}'.", oid, conflictRow.Resolution);

                    // Save the changes when a resolution was determined.
                    if (conflictRow.Resolution != ConflictResolution.None)
                    {
                        this.SaveAndRebuild(currentRow);
                    }

                    // Add to the list of rows.
                    rows.Add(conflictRow);
                }
            }

            // Add the rows to the extension collection.
            this.Rows.AddRange(rows);

            // Remove the OIDs of the conflicts that have been resolved.
            int[] oids = rows.Where(o => o.Resolution != ConflictResolution.None).Select(o => o.OID).ToArray();
            if (this.IsRemovedAfterResolved)
            {
                // ESRI states that the RemoveList method on the ISelectionSet should not used from .NET. Instead, call IGeoDatabaseBridge2.RemoveList.
                set.Remove(oids);
            }

            // Output the statistics for the conflicts.
            int remainder = rows.Count - oids.Length;

            Log.Info("{0} of the {1} row(s) have been resolved and {2} remain in conflict.", oids.Length, rows.Count, remainder);

            // Return true when all of the conflicts have been resolved.
            return(remainder == 0);
        }
Exemple #3
0
 /// <summary>
 ///     Determines whether this instance can resolve the specified conflict type.
 /// </summary>
 /// <param name="conflictType">Type of the conflict.</param>
 /// <param name="conflictClass">The conflict class.</param>
 /// <returns>
 ///     <c>true</c> if this instance can resolve the specified conflict type; otherwise, <c>false</c>.
 /// </returns>
 public virtual bool CanResolve(TableConflictType conflictType, IConflictClass conflictClass)
 {
     return(conflictClass != null);
 }