예제 #1
0
        public DataMapStepOutput(DataMap dataMap,
                                 DataTable sourceData, DuplicateRowBehavior sourceDataDuplicateRowBehavior,
                                 DataTable targetData, DuplicateRowBehavior targetDataDuplicateRowBehavior,
                                 Func <DataRow, bool> rowsToProcess, bool deferExecutionUntilNextStep = false)
        {
            if (dataMap == null)
            {
                throw new Exception("Data map can not be null.");
            }

            if (sourceData == null)
            {
                throw new Exception("Source data can not be null.");
            }

            if (targetData == null)
            {
                throw new Exception("Target data can not be null.");
            }

            DataMap = dataMap;

            SourceData = sourceData;

            SourceDataDuplicateRowBehavior = sourceDataDuplicateRowBehavior;

            TargetData = targetData;

            TargetDataDuplicateRowBehavior = targetDataDuplicateRowBehavior;

            RowsToProcess = rowsToProcess;

            DeferExecutionUntilNextStep = deferExecutionUntilNextStep;
        }
예제 #2
0
 public DataMapStepOutput(DataMap dataMap,
                          DataTable sourceData, DuplicateRowBehavior sourceDataDuplicateRowBehavior,
                          DataTable targetData, DuplicateRowBehavior targetDataDuplicateRowBehavior,
                          bool deferExecutionUntilNextStep = false)
     : this(dataMap, sourceData, sourceDataDuplicateRowBehavior,
            targetData, targetDataDuplicateRowBehavior, null, deferExecutionUntilNextStep)
 {
 }
예제 #3
0
        /// <summary>
        /// Cleans the table of duplicates and returns a collection of keys for removed rows.
        /// </summary>
        /// <returns></returns>
        public static HashSet <RecordKeyCombo> RemoveDuplicates(SyncSide?syncSide, DataTable tbl, List <string> uniqueKeyColumnNames, DuplicateRowBehavior duplicateRowBehavior = DuplicateRowBehavior.ThrowException)
        {
            if (tbl == null)
            {
                throw new Exception("Table can not be null.");
            }

            if (uniqueKeyColumnNames == null || uniqueKeyColumnNames.Count == 0)
            {
                throw new Exception("At least one unique key column name is required.");
            }

            if (uniqueKeyColumnNames.Distinct(StringComparer.OrdinalIgnoreCase).Count() < uniqueKeyColumnNames.Count)
            {
                throw new Exception("All key column names must be unique.");
            }

            var rowsByKey = new Dictionary <RecordKeyCombo, DataRow>(new RecordKeyComboComparer());

            var duplicateRows = new HashSet <DataRow>();

            var duplicateKeys = new HashSet <RecordKeyCombo>(new RecordKeyComboComparer());

            foreach (DataRow row in tbl.Rows)
            {
                var rowKeys = GetKeys(row, uniqueKeyColumnNames);

                if (rowsByKey.ContainsKey(rowKeys))
                {
                    duplicateKeys.Add(rowKeys);

                    duplicateRows.Add(row);

                    if (duplicateRowBehavior == DuplicateRowBehavior.RemoveAllDuplicateRows)
                    {
                        duplicateRows.Add(rowsByKey[rowKeys]);
                    }
                }
                else
                {
                    rowsByKey[rowKeys] = row;
                }
            }

            if (duplicateRows.Count > 0)
            {
                if (duplicateRowBehavior == DuplicateRowBehavior.ThrowException)
                {
                    if (syncSide.HasValue)
                    {
                        throw new Exception(GetDuplicateRowsExceptionMessage(syncSide.Value, tbl.TableName, uniqueKeyColumnNames, duplicateKeys));
                    }
                    else
                    {
                        throw new Exception(GetDuplicateRowsExceptionMessage(tbl.TableName, uniqueKeyColumnNames, duplicateKeys));
                    }
                }
                else
                {
                    SyncEngineLogger.WriteByParallelTaskContext(LogEntryType.Warning, () =>
                    {
                        var msg = new StringBuilder();

                        if (syncSide.HasValue)
                        {
                            msg.Append(GetDuplicateRowsExceptionMessage(syncSide.Value, tbl.TableName, uniqueKeyColumnNames, duplicateKeys));
                        }
                        else
                        {
                            msg.Append(GetDuplicateRowsExceptionMessage(tbl.TableName, uniqueKeyColumnNames, duplicateKeys));
                        }

                        if (duplicateRowBehavior == DuplicateRowBehavior.RemoveAllDuplicateRows)
                        {
                            msg.Append(" All duplicate rows were removed.");
                        }
                        else if (duplicateRowBehavior == DuplicateRowBehavior.RemoveDuplicateRowsExceptFirst)
                        {
                            msg.Append(" All duplicate rows were removed except for the first row for each set of unique keys.");
                        }

                        return(msg.ToString());
                    });
                }
            }

            foreach (var duplicateRow in duplicateRows)
            {
                tbl.Rows.Remove(duplicateRow);
            }

            return(duplicateKeys);
        }
예제 #4
0
 /// <summary>
 /// Cleans the table of duplicates and returns a collection of keys for removed rows.
 /// </summary>
 /// <returns></returns>
 public static HashSet <RecordKeyCombo> RemoveDuplicates(SyncSide?syncSide, DataTable tbl, string uniqueKeyColumnName, DuplicateRowBehavior duplicateRowBehavior = DuplicateRowBehavior.ThrowException)
 {
     return(RemoveDuplicates(syncSide, tbl, new List <string>()
     {
         uniqueKeyColumnName
     }, duplicateRowBehavior));
 }
예제 #5
0
 /// <summary>
 /// Cleans the table of duplicates and returns a collection of keys for removed rows.
 /// </summary>
 /// <returns></returns>
 public static HashSet <RecordKeyCombo> RemoveDuplicates(DataTable tbl, List <string> uniqueKeyColumnNames, DuplicateRowBehavior duplicateRowBehavior = DuplicateRowBehavior.ThrowException)
 {
     return(RemoveDuplicates(null, tbl, uniqueKeyColumnNames, duplicateRowBehavior));
 }
예제 #6
0
        public static EntityBatch Compare(OneToMany_OneWayDataMap map,
                                          DataTable sourceData, DuplicateRowBehavior sourceDataDuplicateRowBehavior,
                                          DataTable targetData, DuplicateRowBehavior targetDataDuplicateRowBehavior)
        {
            if (map == null)
            {
                throw new Exception("Data map can not be null.");
            }

            if (sourceData == null)
            {
                throw new Exception("Source-side data table can not be null.");
            }

            if (targetData == null)
            {
                throw new Exception("Target-side data table can not be null.");
            }

            if (map.EntityToUpdateDefinition.InsertsToExcludeFilter != null)
            {
                throw new Exception("Exclusion filter for inserts is not supported for one-to-many data maps.");
            }

            if (map.EntityToUpdateDefinition.UpdatesToExcludeFilter != null)
            {
                throw new Exception("Exclusion filter for updates is not supported for one-to-many data maps.");
            }

            if (map.EntityToUpdateDefinition.DeletionsToExcludeFilter != null)
            {
                throw new Exception("Exclusion filter for deletions is not supported for one-to-many data maps.");
            }

            if (map.SyncDirection == SyncDirection.SourceToTarget)
            {
                DataTableHelper.RemoveDuplicates(sourceData, map.JoinKeysCollection.JoinFields.Select(d => d.SourceJoinField).ToList(), sourceDataDuplicateRowBehavior);
            }
            else if (map.SyncDirection == SyncDirection.TargetToSource)
            {
                DataTableHelper.RemoveDuplicates(targetData, map.JoinKeysCollection.JoinFields.Select(d => d.TargetJoinField).ToList(), targetDataDuplicateRowBehavior);
            }
            else
            {
                throw new EnumValueNotImplementedException <SyncDirection>(map.SyncDirection);
            }

            //ValidateSyncFieldsExistInDataTables(map, sourceData, targetData);

            //ValidateDataOnlyFieldsExistInMap(map);

            DataTable     oneSideData       = null;
            List <string> oneSideJoinFields = null;

            DataTable     manySideData       = null;
            List <string> manySideJoinFields = null;

            var batch = new EntityBatch(map.EntityToUpdateDefinition);

            if (map.EntityToUpdateDefinition.SyncSide == SyncSide.Source)
            {
                if (map.SyncDirection == SyncDirection.SourceToTarget)
                {
                    throw new Exception(string.Format("{0}-side can not be updated for sync direction '{1}'.",
                                                      Enum.GetName(typeof(SyncSide), map.EntityToUpdateDefinition.SyncSide),
                                                      Enum.GetName(typeof(SyncDirection), map.SyncDirection)));
                }

                ValidateFieldsToTransposeExistInDataTable(targetData, map.ColumnNamesToTranspose);

                oneSideData       = targetData;
                oneSideJoinFields = map.JoinKeysCollection.JoinFields.Select(d => d.TargetJoinField).ToList();

                manySideData       = sourceData;
                manySideJoinFields = map.JoinKeysCollection.JoinFields.Select(d => d.SourceJoinField).ToList();
            }
            else if (map.EntityToUpdateDefinition.SyncSide == SyncSide.Target)
            {
                if (map.SyncDirection == SyncDirection.TargetToSource)
                {
                    throw new Exception(string.Format("{0}-side can not be updated for sync direction '{1}'.",
                                                      Enum.GetName(typeof(SyncSide), map.EntityToUpdateDefinition.SyncSide),
                                                      Enum.GetName(typeof(SyncDirection), map.SyncDirection)));
                }

                ValidateFieldsToTransposeExistInDataTable(sourceData, map.ColumnNamesToTranspose);

                oneSideData       = sourceData;
                oneSideJoinFields = map.JoinKeysCollection.JoinFields.Select(d => d.SourceJoinField).ToList();

                manySideData       = targetData;
                manySideJoinFields = map.JoinKeysCollection.JoinFields.Select(d => d.TargetJoinField).ToList();
            }
            else
            {
                throw new EnumValueNotImplementedException <SyncSide>(map.EntityToUpdateDefinition.SyncSide);
            }

            var customSetFieldsForDelete = map.CustomSetFields
                                           .Where(d => (d.AppliesTo.HasFlag(SyncOperation.Deletes) || d.AppliesTo.HasFlag(SyncOperation.All)));

            var dataOnlyFields = batch.EntityDefinition.DataOnlyFields.ToDictionary(d => d.FieldName, d => d, StringComparer.OrdinalIgnoreCase);

            var manySideRowsLookup = GetManySideRowsDictionary(manySideJoinFields, manySideData);

            foreach (var oneSideRow in oneSideData.Rows.Cast <DataRow>())
            {
                var oneSideRecordKeyCombo = RecordKeyCombo.GetRecordKeyComboFromDataRow(oneSideRow, oneSideJoinFields);

                List <DataRow> manySideFilteredRows = null;

                if (manySideRowsLookup.ContainsKey(oneSideRecordKeyCombo))
                {
                    manySideFilteredRows = manySideRowsLookup[oneSideRecordKeyCombo];
                }
                else
                {
                    manySideFilteredRows = new List <DataRow>();
                }

                foreach (var fieldToTranspose in map.ColumnNamesToTranspose)
                {
                    var transposeResult = map.TransposeMethod(manySideFilteredRows, oneSideRow, fieldToTranspose);

                    if (transposeResult == null)
                    {
                        continue;
                    }

                    var transposeDataOnlyValues = GetTransposeDataOnlyFieldValues(map.EntityToUpdateDefinition.TransposeDataOnlyFields, oneSideRow, manySideFilteredRows, fieldToTranspose);

                    EntityRecord entityRecord;

                    if (transposeResult is TransposeResult_AddRecord && batch.EntityDefinition.ApplyInserts)
                    {
                        entityRecord = AddInsertToBatch(map, batch, dataOnlyFields, oneSideRow, transposeResult, transposeDataOnlyValues);
                    }
                    else if (transposeResult is TransposeResult_UpdateRecord && batch.EntityDefinition.ApplyUpdates)
                    {
                        entityRecord = AddUpdateToBatch(map, batch, dataOnlyFields, oneSideRow, manySideFilteredRows, transposeResult, transposeDataOnlyValues);
                    }
                    else if (transposeResult is TransposeResult_DeleteRecord && batch.EntityDefinition.ApplyDeletions)
                    {
                        entityRecord = AddDeletionToBatch(map, batch, dataOnlyFields, oneSideRow, manySideFilteredRows, transposeResult, transposeDataOnlyValues);
                    }
                    else
                    {
                        throw new DerivedClassNotImplementedException <TransposeResult>(transposeResult);
                    }
                }
            }

            return(batch);
        }