public Translator(SourceTable tbl, IDataReader source, IEnumerable<SourceColumn> srcColumns, Converter[] converter) { if (tbl == null) throw new ArgumentNullException("tbl"); if (source == null) throw new ArgumentNullException("source"); if (srcColumns == null) throw new ArgumentNullException("srcColumns"); //_tbl = tbl; _source = source; _srcColumns = srcColumns.ToArray(); _srcColumnsInfos = _srcColumns.Select( col => new SourceColumnInfo(DbTypeMapper.GetDbTypeForProperty(col.DestinationProperty.Last().GetType()), DbTypeMapper.GetDbType(col.DbType), col.DestinationProperty.Last() is EnumerationProperty, col.DestinationProperty.First() is CompoundObjectProperty)).ToArray(); _converter = converter != null ? converter.ToDictionary(c => c.Column) : new Dictionary<SourceColumn, Converter>(); _resultColumnCount = _srcColumns.Length; if (typeof(IMigrationInfo).IsAssignableFrom(tbl.DestinationObjectClass.GetDataType())) { // TODO: That's a bad hack! _errorColIdx = _resultColumnCount; _resultColumnCount++; } else { _errorColIdx = -1; } foreach (var comp in srcColumns .Where(c => c.DestinationProperty.First() is CompoundObjectProperty) .GroupBy(c => c.DestinationProperty.First())) { foreach (var col in comp) { _compoundObjectSourceColumns[col.Name] = _resultColumnCount; } _resultColumnCount++; } }
public void TableBaseMigration(SourceTable tbl, Converter[] converter, Join[] additional_joins) { // ------------------- Argument checks ------------------- if (tbl == null) throw new ArgumentNullException("tbl"); if (tbl.DestinationObjectClass == null) { Log.InfoFormat("Skipping base migration of unmapped table [{0}]", tbl.Name); return; } using (Log.InfoTraceMethodCallFormat("TableBaseMigration", "{0} to {1}", tbl.Name, tbl.DestinationObjectClass.Name)) { // ------------------- Build columns ------------------- var mappedColumns = tbl.SourceColumn .Where(c => c.DestinationProperty.Count > 0) .OrderBy(c => c.Name) .ToList(); // Ref Cols var referringCols = mappedColumns.Where(c => c.References != null).ToList(); // ------------------- Migrate ------------------- if (referringCols.Count == 0 && (additional_joins == null || additional_joins.Length == 0)) { TableBaseSimpleMigration(tbl, converter, mappedColumns); } else { TableBaseComplexMigration(tbl, converter, mappedColumns, referringCols, additional_joins); } } }
private void TableBaseSimpleMigration(SourceTable tbl, Converter[] nullConverter, List<SourceColumn> mappedColumns) { var dstColumnNames = GetDestinationColumnNames(tbl, mappedColumns); var srcColumnNames = mappedColumns.Select(c => c.Name).ToArray(); var tblRef = _src.GetTableName(tbl.StagingDatabase.Schema, tbl.Name); // no fk mapping required using (var srcReader = _src.ReadTableData(tblRef, srcColumnNames)) using (var translator = new Translator(tbl, srcReader, mappedColumns, nullConverter)) { _dst.WriteTableData(_dst.GetTableName(tbl.DestinationObjectClass.Module.SchemaName, tbl.DestinationObjectClass.TableName), translator, dstColumnNames); WriteLog( tbl.Name, translator.ProcessedRows, tbl.DestinationObjectClass.TableName, translator.ProcessedRows); } }
private void TableBaseComplexMigration(SourceTable tbl, Converter[] converter, List<SourceColumn> mappedColumns, List<SourceColumn> referringCols, Join[] additional_joins) { if (additional_joins != null && additional_joins.Length > 0 && additional_joins.All(j => referringCols .Select(c => c.DestinationProperty.Single()) .OfType<ObjectReferenceProperty>() .Any(orp => j.JoinTableName == _dst.GetTableName(orp.RelationEnd.Parent.GetOtherEnd(orp.RelationEnd).Type.Module.SchemaName, orp.RelationEnd.Parent.GetOtherEnd(orp.RelationEnd).Type.TableName)))) { throw new InvalidOperationException("Unmapped additional joins found"); } // could automatically create needed indices var all_joins = new Dictionary<SourceColumn, Join>(); var root_joins = referringCols .GroupBy(k => k.DestinationProperty.Single()) .SelectMany(referenceGroup => CreateReferenceJoin(referenceGroup, all_joins)) .ToArray(); // Add manual joins IEnumerable<Join> joins; if (additional_joins != null) { joins = root_joins.Union(additional_joins); } else { joins = root_joins; } var srcColumns = mappedColumns .Where(c => c.References == null) .Union( referringCols .GroupBy(k => k.DestinationProperty.Single()) // referring columns cannot be mapped remotely .Select(g => g.First(p => p.References.References == null)) ).ToList(); var srcColumnNames = srcColumns.Select(c => { var orp = c.DestinationProperty.FirstOrDefault() as ObjectReferenceProperty; if (c.References != null) { return new ProjectionColumn("ID", all_joins[c], System.Data.DbType.Int32, c.DestinationProperty.Single().Name); } else if (c.References == null && orp != null) { if (additional_joins != null && additional_joins.Count(i => i.JoinTableName == _dst.GetTableName(orp.RelationEnd.Parent.GetOtherEnd(orp.RelationEnd).Type.Module.SchemaName, orp.RelationEnd.Parent.GetOtherEnd(orp.RelationEnd).Type.TableName)) > 0) { return new ProjectionColumn( "ID", additional_joins.Single(j => j.JoinTableName == _dst.GetTableName(orp.RelationEnd.Parent.GetOtherEnd(orp.RelationEnd).Type.Module.SchemaName, orp.RelationEnd.Parent.GetOtherEnd(orp.RelationEnd).Type.TableName)), System.Data.DbType.Int32, orp.Name); } else if (converter.Any(cnv => cnv.Column.Name == c.Name)) { return new ProjectionColumn(c.Name, ColumnRef.PrimaryTable, c.DestinationProperty.Single().Name); } else { throw new InvalidOperationException(string.Format("No join found for {0}", c)); } } else { return new ProjectionColumn(c.Name, ColumnRef.PrimaryTable, (System.Data.DbType)c.DbType, null); } }).ToList(); var dstColumnNames = GetDestinationColumnNames(tbl, srcColumns); long processedRows; using (var srcReader = _src.ReadJoin(_src.GetTableName(tbl.StagingDatabase.Schema, tbl.Name), srcColumnNames, joins)) using (var translator = new Translator(tbl, srcReader, srcColumns, converter)) { _dst.WriteTableData(_dst.GetTableName(tbl.DestinationObjectClass.Module.SchemaName, tbl.DestinationObjectClass.TableName), translator, dstColumnNames); processedRows = translator.ProcessedRows; } // count rows in original table, joins should not add or remove rows WriteLog( tbl.Name, _src.CountRows(_src.GetTableName(tbl.StagingDatabase.Schema, tbl.Name)), tbl.DestinationObjectClass.TableName, processedRows); }