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); }