Exemplo n.º 1
0
        private void BuildMappingTable()
        {
            //Get a new mapping table in memory
            _mappingTable = new Dictionary <object, List <object> >();

            //connect to server and run distinct query
            var server = MappingFromColumn.TableInfo.Discover(DataAccessContext.DataLoad).Database.Server;

            var fromColumnName = MappingFromColumn.GetRuntimeName();
            var toColumnName   = MappingToColumn.GetRuntimeName();

            //pull back all the data
            using (var con = server.GetConnection())
            {
                con.Open();
                var sql = GetMappingTableSql();
                var cmd = server.GetCommand(sql, con);
                cmd.CommandTimeout = Timeout;

                var r = cmd.ExecuteReader();

                while (r.Read())
                {
                    if (!_mappingTable.ContainsKey(r[fromColumnName]))
                    {
                        _mappingTable.Add(r[fromColumnName], new List <object>());
                    }

                    _mappingTable[r[fromColumnName]].Add(r[toColumnName]);
                }
            }
        }
Exemplo n.º 2
0
        public DataTable ProcessPipelineData(DataTable toProcess, IDataLoadEventListener listener, GracefulCancellationToken cancellationToken)
        {
            var fromColumnName = MappingFromColumn.GetRuntimeName();
            var toColumnName   = MappingToColumn.GetRuntimeName();

            listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "About to build mapping table"));

            if (!toProcess.Columns.Contains(fromColumnName))
            {
                throw new Exception("DataTable did not contain a field called '" + fromColumnName + "'");
            }

            if (toProcess.Columns.Contains(toColumnName))
            {
                throw new Exception("DataTable already contained a field '" + toColumnName + "'");
            }

            if (_mappingTable == null)
            {
                BuildMappingTable();
            }

            listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Mapping table resulted in " + _mappingTable.Count + " unique possible input values"));

            listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Mapping table resulted in " + _mappingTable.Sum(kvp => kvp.Value.Count) + " unique possible output values"));

            //add the new column (the output column)
            toProcess.Columns.Add(toColumnName);

            int idxFrom = toProcess.Columns.IndexOf(fromColumnName);
            int idxTo   = toProcess.Columns.IndexOf(toColumnName);

            int numberOfElementsPerRow = toProcess.Columns.Count;

            List <object[]> newRows = new List <object[]>();
            List <DataRow>  toDrop  = new List <DataRow>();

            foreach (DataRow row in toProcess.Rows)
            {
                var fromValue = row[idxFrom];

                //if we don't have the key value
                if (!_mappingTable.ContainsKey(fromValue))
                {
                    if (CrashIfNoMappingsFound)
                    {
                        throw new KeyNotFoundException("Could not find mapping for " + fromValue);
                    }
                    else
                    {
                        listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, "No mapping for '" + fromValue + "' dropping row"));
                        toDrop.Add(row);
                        continue;
                    }
                }

                //we do have the key value!
                var results = _mappingTable[fromValue];

                //yes 1
                if (results.Count == 1)
                {
                    row[idxTo] = results.Single();
                }
                else
                {
                    //great we have multiple mappings, bob=>Frank and bob=>Jesus.  What does the user want to do about that
                    switch (AliasResolutionStrategy)
                    {
                    case AliasResolutionStrategy.CrashIfAliasesFound:
                        throw new AliasException("The value '" + fromValue + "' maps to mulitple ouptut values:" + string.Join(",", results.Select(v => "'" + v.ToString() + "'")));

                    case AliasResolutionStrategy.MultiplyInputDataRowsByAliases:

                        //substitute for the first alias (bob=>Frank)
                        row[idxTo] = results.First();

                        //then clone the row and do a row with bob=>Jesus
                        foreach (object next in results.Skip(1))
                        {
                            //Create a copy of the input row
                            object[] newRow = new object[numberOfElementsPerRow];
                            row.ItemArray.CopyTo(newRow, 0);

                            //Set the aliasable element to the alias
                            newRow[idxTo] = next;

                            //Add it to our new rows collection
                            newRows.Add(newRow);
                        }

                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }

            //add any alias multiplication rows
            foreach (object[] newRow in newRows)
            {
                toProcess.Rows.Add(newRow);
            }

            //drop rows with missing identifiers
            foreach (DataRow dropRow in toDrop)
            {
                toProcess.Rows.Remove(dropRow);
            }

            if (!KeepInputColumnToo)
            {
                toProcess.Columns.Remove(fromColumnName);
            }

            return(toProcess);
        }