예제 #1
0
        /// <summary>
        ///     Gets the rows that have differences in the given fields.
        /// </summary>
        /// <param name="fieldName">Name of the field.</param>
        /// <returns>
        ///     Returns a <see cref="IEnumerable{T}" /> representing the rows that have differences.
        /// </returns>
        /// <exception cref="System.ArgumentOutOfRangeException">
        ///     sourceFieldName
        ///     or
        ///     targetFieldName
        /// </exception>
        public IEnumerable <IRow> GetRows(string fieldName)
        {
            var equailityComparer = new FieldsEqualityComparer();

            foreach (var source in this.GetRows(DeltaRowChangeVersion.SourceVersion))
            {
                var s = source.Fields.FindField(fieldName);
                if (s == -1)
                {
                    throw new ArgumentOutOfRangeException("fieldName");
                }

                foreach (var target in this.GetRows(DeltaRowChangeVersion.SourceVersion))
                {
                    var t = target.Fields.FindField(fieldName);
                    if (t == -1)
                    {
                        throw new ArgumentOutOfRangeException("fieldName");
                    }

                    if (!equailityComparer.Equals(source, target, s))
                    {
                        yield return(source);
                    }
                }
            }
        }
예제 #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);
        }