예제 #1
0
 public abstract string GenerateSchemaScripts(SchemaInfo schemaInfo);
예제 #2
0
        public virtual async Task <string> GenerateDataScriptsAsync(SchemaInfo schemaInfo)
        {
            StringBuilder sb = new StringBuilder();

            if (Option.ScriptOutputMode == GenerateScriptOutputMode.WriteToFile)
            {
                this.AppendScriptsToFile("", GenerateScriptMode.Data, true);
            }

            int i           = 0;
            int pickupIndex = -1;

            if (schemaInfo.PickupTable != null)
            {
                foreach (Table table in schemaInfo.Tables)
                {
                    if (table.Owner == schemaInfo.PickupTable.Owner && table.Name == schemaInfo.PickupTable.Name)
                    {
                        pickupIndex = i;
                        break;
                    }
                    i++;
                }
            }

            i = 0;
            using (DbConnection connection = this.GetDbConnector().CreateConnection())
            {
                int tableCount = schemaInfo.Tables.Count - (pickupIndex == -1 ? 0 : pickupIndex + 1);
                int count      = 0;
                foreach (Table table in schemaInfo.Tables)
                {
                    if (i < pickupIndex)
                    {
                        i++;
                        continue;
                    }

                    count++;
                    string             strTableCount = $"({count}/{tableCount})";
                    string             tableName     = table.Name;
                    List <TableColumn> columns       = schemaInfo.Columns.Where(item => item.Owner == table.Owner && item.TableName == tableName).OrderBy(item => item.Order).ToList();

                    bool isSelfReference = TableReferenceHelper.IsSelfReference(tableName, schemaInfo.TableForeignKeys);

                    List <TablePrimaryKey> primaryKeys = schemaInfo.TablePrimaryKeys.Where(item => item.Owner == table.Owner && item.TableName == tableName).ToList();
                    string primaryKeyColumns           = string.Join(",", primaryKeys.OrderBy(item => item.Order).Select(item => GetQuotedString(item.ColumnName)));

                    long total = await this.GetTableRecordCountAsync(connection, table);

                    if (Option.DataGenerateThreshold.HasValue && total > Option.DataGenerateThreshold.Value)
                    {
                        continue;
                    }

                    int pageSize = Option.DataBatchSize;

                    this.FeedbackInfo($"{strTableCount}Begin to read data from table {table.Name}, total rows:{total}.");

                    Dictionary <long, List <Dictionary <string, object> > > dictPagedData;
                    if (isSelfReference)
                    {
                        string parentColumnName = schemaInfo.TableForeignKeys.FirstOrDefault(item =>
                                                                                             item.Owner == table.Owner &&
                                                                                             item.TableName == tableName &&
                                                                                             item.ReferencedTableName == tableName)?.ColumnName;

                        string strWhere = $" WHERE {GetQuotedString(parentColumnName)} IS NULL";
                        dictPagedData = this.GetSortedPageDatas(connection, table, primaryKeyColumns, parentColumnName, columns, Option, strWhere);
                    }
                    else
                    {
                        dictPagedData = await this.GetPagedDataListAsync(connection, table, columns, primaryKeyColumns, total, pageSize);
                    }

                    this.FeedbackInfo($"{strTableCount}End read data from table {table.Name}.");

                    this.AppendDataScripts(Option, sb, table, columns, dictPagedData);

                    i++;
                }
            }

            var dataScripts = string.Empty;

            try
            {
                dataScripts = sb.ToString();
            }
            catch (OutOfMemoryException ex)
            {
                //ignore
            }
            finally
            {
                sb.Clear();
            }
            return(dataScripts);
        }
 public override string GenerateDataScripts(SchemaInfo schemaInfo)
 {
     return(base.GenerateDataScripts(schemaInfo));
 }
 public override async Task <string> GenerateDataScriptsAsync(SchemaInfo schemaInfo)
 {
     return(await base.GenerateDataScriptsAsync(schemaInfo));
 }
예제 #5
0
        public static SchemaInfo Clone(SchemaInfo schemaInfo)
        {
            SchemaInfo cloneSchemaInfo = (SchemaInfo)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(schemaInfo), typeof(SchemaInfo));

            return(cloneSchemaInfo);
        }
        public override string GenerateSchemaScripts(SchemaInfo schemaInfo)
        {
            StringBuilder sb = new StringBuilder();

            #region Create Table
            foreach (Table table in schemaInfo.Tables)
            {
                string tableName       = table.Name;
                string quotedTableName = this.GetQuotedTableName(table);

                IEnumerable <TableColumn> tableColumns = schemaInfo.Columns.Where(item => item.TableName == tableName).OrderBy(item => item.Order);

                IEnumerable <TablePrimaryKey> primaryKeys = schemaInfo.TablePrimaryKeys.Where(item => item.TableName == tableName);

                #region Create Table

                sb.Append(
                    $@"
CREATE TABLE {quotedTableName}(
{string.Join("," + Environment.NewLine, tableColumns.Select(item => this.TranslateColumn(table, item))).TrimEnd(',')}
)
TABLESPACE
{this.ConnectionInfo.Database};");
                #endregion

                sb.AppendLine();

                #region Comment
                if (!string.IsNullOrEmpty(table.Comment))
                {
                    sb.AppendLine($"COMMENT ON TABLE {this.ConnectionInfo.UserId}.{GetQuotedString(tableName)} IS '{ValueHelper.TransferSingleQuotation(table.Comment)}';");
                }

                foreach (TableColumn column in tableColumns.Where(item => !string.IsNullOrEmpty(item.Comment)))
                {
                    sb.AppendLine($"COMMENT ON COLUMN {this.ConnectionInfo.UserId}.{GetQuotedString(tableName)}.{GetQuotedString(column.ColumnName)} IS '{ValueHelper.TransferSingleQuotation(column.Comment)}';");
                }
                #endregion

                #region Primary Key
                if (Option.GenerateKey && primaryKeys.Count() > 0)
                {
                    string primaryKey =
                        $@"
ALTER TABLE {quotedTableName} ADD CONSTRAINT {primaryKeys.FirstOrDefault().KeyName} PRIMARY KEY 
(
{string.Join(Environment.NewLine, primaryKeys.Select(item => $"{ GetQuotedString(item.ColumnName)},")).TrimEnd(',')}
)
USING INDEX 
TABLESPACE
{this.ConnectionInfo.Database}
;";
                    sb.Append(primaryKey);
                }
                #endregion

                #region Foreign Key
                if (Option.GenerateKey)
                {
                    IEnumerable <TableForeignKey> foreignKeys = schemaInfo.TableForeignKeys.Where(item => item.TableName == tableName);
                    if (foreignKeys.Count() > 0)
                    {
                        sb.AppendLine();
                        ILookup <string, TableForeignKey> foreignKeyLookup = foreignKeys.ToLookup(item => item.KeyName);

                        IEnumerable <string> keyNames = foreignKeyLookup.Select(item => item.Key);

                        foreach (string keyName in keyNames)
                        {
                            TableForeignKey tableForeignKey = foreignKeyLookup[keyName].First();

                            string columnNames         = string.Join(",", foreignKeyLookup[keyName].Select(item => $"{GetQuotedString(item.ColumnName)}"));
                            string referenceColumnName = string.Join(",", foreignKeyLookup[keyName].Select(item => $"{GetQuotedString(item.ReferencedColumnName)}"));

                            sb.Append(
                                $@"
ALTER TABLE {quotedTableName} ADD CONSTRAINT { GetQuotedString(keyName)} FOREIGN KEY ({columnNames})
REFERENCES { GetQuotedString(tableForeignKey.ReferencedTableName)}({referenceColumnName})
");

                            if (tableForeignKey.DeleteCascade)
                            {
                                sb.AppendLine("ON DELETE CASCADE");
                            }

                            sb.Append(";");
                        }
                    }
                }
                #endregion

                #region Index
                if (Option.GenerateIndex)
                {
                    IEnumerable <TableIndex> indices = schemaInfo.TableIndices.Where(item => item.TableName == tableName).OrderBy(item => item.Order);
                    if (indices.Count() > 0)
                    {
                        sb.AppendLine();

                        List <string> indexColumns = new List <string>();

                        ILookup <string, TableIndex> indexLookup = indices.ToLookup(item => item.IndexName);
                        IEnumerable <string>         indexNames  = indexLookup.Select(item => item.Key);
                        foreach (string indexName in indexNames)
                        {
                            TableIndex tableIndex = indexLookup[indexName].First();

                            string columnNames = string.Join(",", indexLookup[indexName].Select(item => $"{GetQuotedString(item.ColumnName)}"));

                            if (indexColumns.Contains(columnNames))
                            {
                                continue;
                            }

                            sb.AppendLine($"CREATE {(tableIndex.IsUnique ? "UNIQUE" : "")} INDEX { GetQuotedString(tableIndex.IndexName)} ON { GetQuotedString(tableName)} ({columnNames});");

                            if (!indexColumns.Contains(columnNames))
                            {
                                indexColumns.Add(columnNames);
                            }
                        }
                    }
                }
                #endregion

                //#region Default Value
                //if (options.GenerateDefaultValue)
                //{
                //    IEnumerable<TableColumn> defaultValueColumns = columns.Where(item => item.TableName == tableName && !string.IsNullOrEmpty(item.DefaultValue));
                //    foreach (TableColumn column in defaultValueColumns)
                //    {
                //        sb.AppendLine($"ALTER TABLE \"{tableName}\" MODIFY \"{column.ColumnName}\" DEFAULT {column.DefaultValue};");
                //    }
                //}
                //#endregion
            }
            #endregion

            return(sb.ToString());
        }
예제 #7
0
        private async Task InternalConvert(SchemaInfo schemaInfo = null, bool getAllIfNotSpecified = true, bool async = false)
        {
            DbInterpreter sourceInterpreter = this.Source.DbInterpreter;

            sourceInterpreter.Option.TreatBytesAsNullForScript = true;

            string[] tableNames           = null;
            string[] userDefinedTypeNames = null;
            string[] viewNames            = null;

            if (schemaInfo == null || getAllIfNotSpecified)
            {
                tableNames           = sourceInterpreter.GetTables().Select(item => item.Name).ToArray();
                userDefinedTypeNames = sourceInterpreter.GetUserDefinedTypes().Select(item => item.Name).ToArray();
                viewNames            = sourceInterpreter.GetViews().Select(item => item.Name).ToArray();
            }
            else
            {
                tableNames           = schemaInfo.Tables.Select(t => t.Name).ToArray();
                userDefinedTypeNames = schemaInfo.UserDefinedTypes.Select(item => item.Name).ToArray();
                viewNames            = schemaInfo.Views.Select(item => item.Name).ToArray();
            }

            SelectionInfo selectionInfo = new SelectionInfo()
            {
                UserDefinedTypeNames = userDefinedTypeNames,
                TableNames           = tableNames,
                ViewNames            = viewNames
            };

            SchemaInfo sourceSchemaInfo = async? await sourceInterpreter.GetSchemaInfoAsync(selectionInfo, getAllIfNotSpecified):
                                          sourceInterpreter.GetSchemaInfo(selectionInfo, getAllIfNotSpecified);

            SchemaInfo targetSchemaInfo = SchemaInfoHelper.Clone(sourceSchemaInfo);

            if (!string.IsNullOrEmpty(this.Target.DbOwner))
            {
                SchemaInfoHelper.TransformOwner(targetSchemaInfo, this.Target.DbOwner);
            }

            targetSchemaInfo.Columns = ColumnTranslator.Translate(targetSchemaInfo.Columns, this.Source.DbInterpreter.DatabaseType, this.Target.DbInterpreter.DatabaseType);
            targetSchemaInfo.Views   = ViewTranslator.Translate(targetSchemaInfo.Views, sourceInterpreter, this.Target.DbInterpreter, this.Target.DbOwner);

            if (this.Option.EnsurePrimaryKeyNameUnique)
            {
                SchemaInfoHelper.EnsurePrimaryKeyNameUnique(targetSchemaInfo);
            }

            if (this.Option.EnsureIndexNameUnique)
            {
                SchemaInfoHelper.EnsureIndexNameUnique(targetSchemaInfo);
            }

            DbInterpreter targetInterpreter = this.Target.DbInterpreter;
            bool          generateIdentity  = targetInterpreter.Option.GenerateIdentity;

            if (generateIdentity)
            {
                targetInterpreter.Option.InsertIdentityValue = true;
            }

            string script = "";

            sourceInterpreter.Subscribe(this);
            targetInterpreter.Subscribe(this);

            if (this.Option.GenerateScriptMode.HasFlag(GenerateScriptMode.Schema))
            {
                script = targetInterpreter.GenerateSchemaScripts(targetSchemaInfo);

                if (string.IsNullOrEmpty(script))
                {
                    throw new Exception($"The script to create schema is null.");
                }

                targetInterpreter.Feedback(FeedbackInfoType.Info, "Begin to sync schema...");
                if (!this.Option.SplitScriptsToExecute)
                {
                    if (targetInterpreter is SqlServerInterpreter)
                    {
                        string[] scriptItems = script.Split(new string[] { "GO" + Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                        if (async)
                        {
                            scriptItems.ToList().ForEach(async item =>
                            {
                                await targetInterpreter.ExecuteNonQueryAsync(item);
                            });
                        }
                        else
                        {
                            scriptItems.ToList().ForEach(item =>
                            {
                                targetInterpreter.ExecuteNonQuery(item);
                            });
                        }
                    }
                    else
                    {
                        if (async)
                        {
                            await targetInterpreter.ExecuteNonQueryAsync(script);
                        }
                        else
                        {
                            targetInterpreter.ExecuteNonQuery(script);
                        }
                    }
                }
                else
                {
                    string[] sqls  = script.Split(new char[] { this.Option.ScriptSplitChar }, StringSplitOptions.RemoveEmptyEntries);
                    int      count = sqls.Count();

                    int i = 0;
                    foreach (string sql in sqls)
                    {
                        if (!string.IsNullOrEmpty(sql.Trim()))
                        {
                            i++;
                            targetInterpreter.Feedback(FeedbackInfoType.Info, $"({i}/{count}), executing {sql}");
                            targetInterpreter.ExecuteNonQuery(sql.Trim());
                        }
                    }
                }
                targetInterpreter.Feedback(FeedbackInfoType.Info, "End sync schema.");
            }

            if (this.Option.GenerateScriptMode.HasFlag(GenerateScriptMode.Data))
            {
                List <TableColumn> identityTableColumns = new List <TableColumn>();
                if (generateIdentity)
                {
                    identityTableColumns = targetSchemaInfo.Columns.Where(item => item.IsIdentity).ToList();
                }

                if (this.Option.PickupTable != null)
                {
                    sourceSchemaInfo.PickupTable = this.Option.PickupTable;
                }

                sourceInterpreter.AppendScriptsToFile("", GenerateScriptMode.Data, true);
                targetInterpreter.AppendScriptsToFile("", GenerateScriptMode.Data, true);

                using (DbConnection dbConnection = targetInterpreter.GetDbConnector().CreateConnection())
                {
                    identityTableColumns.ForEach(item =>
                    {
                        if (targetInterpreter.DatabaseType == DatabaseType.SqlServer)
                        {
                            targetInterpreter.SetIdentityEnabled(dbConnection, item, false);
                        }
                    });

                    sourceInterpreter.OnDataRead += async(table, columns, data, dbDataReader) =>
                    {
                        try
                        {
                            StringBuilder sb = new StringBuilder();

                            (Table Table, List <TableColumn> Columns)targetTableAndColumns = this.GetTargetTableColumns(targetSchemaInfo, this.Target.DbOwner, table, columns);

                            Dictionary <string, object> paramters = targetInterpreter.AppendDataScripts(this.Target.DbInterpreter.Option, sb, targetTableAndColumns.Table, targetTableAndColumns.Columns, new Dictionary <long, List <Dictionary <string, object> > >()
                            {
                                { 1, data }
                            });

                            try
                            {
                                script = sb.ToString();
                                sb.Clear();
                            }
                            catch (OutOfMemoryException e)
                            {
                                sb.Clear();
                            }

                            if (!this.Option.SplitScriptsToExecute)
                            {
                                if (this.Option.BulkCopy && targetInterpreter.SupportBulkCopy)
                                {
                                    if (async)
                                    {
                                        await targetInterpreter.BulkCopyAsync(dbConnection, dbDataReader, table.Name);
                                    }
                                    else
                                    {
                                        targetInterpreter.BulkCopy(dbConnection, dbDataReader, table.Name);
                                    }
                                }
                                else
                                {
                                    if (async)
                                    {
                                        await targetInterpreter.ExecuteNonQueryAsync(dbConnection, script, paramters, false);
                                    }
                                    else
                                    {
                                        targetInterpreter.ExecuteNonQuery(dbConnection, script, paramters, false);
                                    }
                                }
                            }
                            else
                            {
                                string[] sqls = script.Split(new char[] { this.Option.ScriptSplitChar }, StringSplitOptions.RemoveEmptyEntries);

                                foreach (string sql in sqls)
                                {
                                    if (!string.IsNullOrEmpty(sql.Trim()))
                                    {
                                        if (this.Option.BulkCopy && targetInterpreter.SupportBulkCopy)
                                        {
                                            if (async)
                                            {
                                                await targetInterpreter.BulkCopyAsync(dbConnection, dbDataReader, table.Name);
                                            }
                                            else
                                            {
                                                targetInterpreter.BulkCopy(dbConnection, dbDataReader, table.Name);
                                            }
                                        }
                                        else
                                        {
                                            if (async)
                                            {
                                                await targetInterpreter.ExecuteNonQueryAsync(dbConnection, sql, paramters, false);
                                            }
                                            else
                                            {
                                                targetInterpreter.ExecuteNonQuery(dbConnection, sql, paramters, false);
                                            }
                                        }
                                    }
                                }
                            }

                            targetInterpreter.FeedbackInfo($"End write data to table {table.Name}, handled rows count:{data.Count}.");
                        }
                        catch (Exception ex)
                        {
                            ConnectionInfo sourceConnectionInfo = sourceInterpreter.ConnectionInfo;
                            ConnectionInfo targetConnectionInfo = targetInterpreter.ConnectionInfo;

                            throw new TableDataTransferException(ex)
                                  {
                                      SourceServer    = sourceConnectionInfo.Server,
                                      SourceDatabase  = sourceConnectionInfo.Database,
                                      SourceTableName = table.Name,
                                      TargetServer    = targetConnectionInfo.Server,
                                      TargetDatabase  = targetConnectionInfo.Database,
                                      TargetTableName = table.Name
                                  };
                        }
                    };

                    if (async)
                    {
                        await sourceInterpreter.GenerateDataScriptsAsync(sourceSchemaInfo);
                    }
                    else
                    {
                        sourceInterpreter.GenerateDataScripts(sourceSchemaInfo);
                    }

                    identityTableColumns.ForEach(item =>
                    {
                        if (targetInterpreter.DatabaseType == DatabaseType.SqlServer)
                        {
                            targetInterpreter.SetIdentityEnabled(dbConnection, item, true);
                        }
                    });
                }
            }
        }
예제 #8
0
        public override string GenerateSchemaScripts(SchemaInfo schemaInfo)
        {
            StringBuilder sb = new StringBuilder();

            #region Create Table
            foreach (Table table in schemaInfo.Tables)
            {
                string tableName       = table.Name;
                string quotedTableName = this.GetQuotedTableName(table);

                IEnumerable <TableColumn> tableColumns = schemaInfo.Columns.Where(item => item.TableName == tableName).OrderBy(item => item.Order);

                string primaryKey = "";

                IEnumerable <TablePrimaryKey> primaryKeys = schemaInfo.TablePrimaryKeys.Where(item => item.TableName == tableName);

                #region Primary Key
                if (Option.GenerateKey && primaryKeys.Count() > 0)
                {
                    //string primaryKeyName = primaryKeys.First().KeyName;
                    //if(primaryKeyName=="PRIMARY")
                    //{
                    //    primaryKeyName = "PK_" + tableName ;
                    //}
                    primaryKey =
                        $@"
,PRIMARY KEY
(
{string.Join(Environment.NewLine, primaryKeys.Select(item => $"{GetQuotedString(item.ColumnName)},")).TrimEnd(',')}
)";
                }
                #endregion

                List <string> foreignKeysLines = new List <string>();
                #region Foreign Key
                if (Option.GenerateKey)
                {
                    IEnumerable <TableForeignKey> foreignKeys = schemaInfo.TableForeignKeys.Where(item => item.TableName == tableName);
                    if (foreignKeys.Count() > 0)
                    {
                        ILookup <string, TableForeignKey> foreignKeyLookup = foreignKeys.ToLookup(item => item.KeyName);

                        IEnumerable <string> keyNames = foreignKeyLookup.Select(item => item.Key);

                        foreach (string keyName in keyNames)
                        {
                            TableForeignKey tableForeignKey = foreignKeyLookup[keyName].First();

                            string columnNames         = string.Join(",", foreignKeyLookup[keyName].Select(item => GetQuotedString(item.ColumnName)));
                            string referenceColumnName = string.Join(",", foreignKeyLookup[keyName].Select(item => $"{GetQuotedString(item.ReferencedColumnName)}"));

                            string line = $"CONSTRAINT {GetQuotedString(keyName)} FOREIGN KEY ({columnNames}) REFERENCES {GetQuotedString(tableForeignKey.ReferencedTableName)}({referenceColumnName})";

                            if (tableForeignKey.UpdateCascade)
                            {
                                line += " ON UPDATE CASCADE";
                            }
                            else
                            {
                                line += " ON UPDATE NO ACTION";
                            }

                            if (tableForeignKey.DeleteCascade)
                            {
                                line += " ON DELETE CASCADE";
                            }
                            else
                            {
                                line += " ON DELETE NO ACTION";
                            }

                            foreignKeysLines.Add(line);
                        }
                    }
                }
                #endregion

                #region Create Table
                sb.Append(
                    $@"
CREATE TABLE {quotedTableName}(
{string.Join("," + Environment.NewLine, tableColumns.Select(item => this.TranslateColumn(table, item)))}{primaryKey}
{(foreignKeysLines.Count > 0 ? ("," + string.Join("," + Environment.NewLine, foreignKeysLines)) : "")}
){(!string.IsNullOrEmpty(table.Comment) ? ($"comment='{ValueHelper.TransferSingleQuotation(table.Comment)}'") : "")}
DEFAULT CHARSET={DbCharset};");
                #endregion

                sb.AppendLine();

                #region Index
                if (Option.GenerateIndex)
                {
                    IEnumerable <TableIndex> indices = schemaInfo.TableIndices.Where(item => item.TableName == tableName).OrderBy(item => item.Order);
                    if (indices.Count() > 0)
                    {
                        sb.AppendLine();

                        List <string> indexColumns = new List <string>();


                        ILookup <string, TableIndex> indexLookup = indices.ToLookup(item => item.IndexName);
                        IEnumerable <string>         indexNames  = indexLookup.Select(item => item.Key);
                        foreach (string indexName in indexNames)
                        {
                            TableIndex tableIndex = indexLookup[indexName].First();

                            string columnNames = string.Join(",", indexLookup[indexName].Select(item => $"{GetQuotedString(item.ColumnName)}"));

                            if (indexColumns.Contains(columnNames))
                            {
                                continue;
                            }

                            var tempIndexName = tableIndex.IndexName;
                            if (tempIndexName.Contains("-"))
                            {
                                tempIndexName = tempIndexName.Replace("-", "_");
                            }

                            sb.AppendLine($"ALTER TABLE {quotedTableName} ADD {(tableIndex.IsUnique ? "UNIQUE" : "")} INDEX {tempIndexName} ({columnNames});");

                            if (!indexColumns.Contains(columnNames))
                            {
                                indexColumns.Add(columnNames);
                            }
                        }
                    }
                }
                #endregion

                //#region Default Value
                //if (options.GenerateDefaultValue)
                //{
                //    IEnumerable<TableColumn> defaultValueColumns = columns.Where(item => item.Owner== table.Owner && item.TableName == tableName && !string.IsNullOrEmpty(item.DefaultValue));
                //    foreach (TableColumn column in defaultValueColumns)
                //    {
                //        sb.AppendLine($"ALTER TABLE {quotedTableName} ALTER COLUMN {GetQuotedString(column.ColumnName)} SET DEFAULT {column.DefaultValue};");
                //    }
                //}
                //#endregion
            }
            #endregion

            return(sb.ToString());
        }
예제 #9
0
 public Task ConvertAsync(SchemaInfo schemaInfo = null, bool getAllIfNotSpecified = true)
 {
     return(this.InternalConvert(schemaInfo, getAllIfNotSpecified, true));
 }
예제 #10
0
 public void Convert(SchemaInfo schemaInfo = null, bool getAllIfNotSpecified = true)
 {
     this.InternalConvert(schemaInfo, getAllIfNotSpecified, false).Wait();
 }
예제 #11
0
        private async Task InternalConvert(SchemaInfo schemaInfo = null)
        {
            DbInterpreter sourceInterpreter = this.Source.DbInterpreter;

            sourceInterpreter.Option.TreatBytesAsNullForScript = true;

            SelectionInfo selectionInfo = new SelectionInfo();

            if (schemaInfo != null)
            {
                selectionInfo.UserDefinedTypeNames = schemaInfo.UserDefinedTypes.Select(item => item.Name).ToArray();
                selectionInfo.TableNames           = schemaInfo.Tables.Select(t => t.Name).ToArray();
                selectionInfo.ViewNames            = schemaInfo.Views.Select(item => item.Name).ToArray();
            }

            SchemaInfo sourceSchemaInfo = await sourceInterpreter.GetSchemaInfoAsync(selectionInfo);

            #region Set data type by user define type

            List <UserDefinedType> utypes = await sourceInterpreter.GetUserDefinedTypesAsync();

            if (utypes != null && utypes.Count > 0)
            {
                foreach (TableColumn column in sourceSchemaInfo.TableColumns)
                {
                    UserDefinedType utype = utypes.FirstOrDefault(item => item.Name == column.DataType);
                    if (utype != null)
                    {
                        column.DataType  = utype.Type;
                        column.MaxLength = utype.MaxLength;
                    }
                }
            }

            #endregion

            SchemaInfo targetSchemaInfo = SchemaInfoHelper.Clone(sourceSchemaInfo);

            if (!string.IsNullOrEmpty(this.Target.DbOwner))
            {
                SchemaInfoHelper.TransformOwner(targetSchemaInfo, this.Target.DbOwner);
            }

            ColumnTranslator columnTranslator = new ColumnTranslator(targetSchemaInfo.TableColumns, this.Source.DbInterpreter.DatabaseType, this.Target.DbInterpreter.DatabaseType);
            targetSchemaInfo.TableColumns = columnTranslator.Translate();

            ViewTranslator viewTranslator = new ViewTranslator(targetSchemaInfo.Views, sourceInterpreter, this.Target.DbInterpreter, this.Target.DbOwner);
            targetSchemaInfo.Views = viewTranslator.Translate();

            if (this.Option.EnsurePrimaryKeyNameUnique)
            {
                SchemaInfoHelper.EnsurePrimaryKeyNameUnique(targetSchemaInfo);
            }

            if (this.Option.EnsureIndexNameUnique)
            {
                SchemaInfoHelper.EnsureIndexNameUnique(targetSchemaInfo);
            }

            DbInterpreter targetInterpreter = this.Target.DbInterpreter;
            bool          generateIdentity  = targetInterpreter.Option.GenerateIdentity;

            if (generateIdentity)
            {
                targetInterpreter.Option.InsertIdentityValue = true;
            }

            string script = "";

            sourceInterpreter.Subscribe(this.observer);
            targetInterpreter.Subscribe(this.observer);

            DataTransferErrorProfile dataErrorProfile = null;

            using (DbConnection dbConnection = targetInterpreter.GetDbConnector().CreateConnection())
            {
                this.isBusy = true;

                if (this.Option.UseTransaction)
                {
                    dbConnection.Open();
                    this.transaction = dbConnection.BeginTransaction();
                }

                #region Schema sync
                if (this.Option.GenerateScriptMode.HasFlag(GenerateScriptMode.Schema))
                {
                    script = targetInterpreter.GenerateSchemaScripts(targetSchemaInfo);

                    if (this.Option.ExecuteScriptOnTargetServer)
                    {
                        if (string.IsNullOrEmpty(script))
                        {
                            this.Feedback(targetInterpreter, $"The script to create schema is empty.", FeedbackInfoType.Error);
                            return;
                        }

                        targetInterpreter.Feedback(FeedbackInfoType.Info, "Begin to sync schema...");

                        try
                        {
                            if (!this.Option.SplitScriptsToExecute)
                            {
                                targetInterpreter.Feedback(FeedbackInfoType.Info, script);

                                await targetInterpreter.ExecuteNonQueryAsync(dbConnection, this.GetCommandInfo(script, null, this.transaction));
                            }
                            else
                            {
                                string[] sqls  = script.Split(new string[] { targetInterpreter.ScriptsSplitString }, StringSplitOptions.RemoveEmptyEntries);
                                int      count = sqls.Count();

                                int i = 0;
                                foreach (string sql in sqls)
                                {
                                    if (!string.IsNullOrEmpty(sql.Trim()))
                                    {
                                        i++;

                                        if (!targetInterpreter.HasError)
                                        {
                                            targetInterpreter.Feedback(FeedbackInfoType.Info, $"({i}/{count}), executing:{Environment.NewLine} {sql}");
                                            await targetInterpreter.ExecuteNonQueryAsync(dbConnection, this.GetCommandInfo(sql.Trim(), null, transaction));
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            targetInterpreter.CancelRequested = true;

                            this.Rollback();

                            ConnectionInfo sourceConnectionInfo = sourceInterpreter.ConnectionInfo;
                            ConnectionInfo targetConnectionInfo = targetInterpreter.ConnectionInfo;

                            SchemaTransferException schemaTransferException = new SchemaTransferException(ex)
                            {
                                SourceServer   = sourceConnectionInfo.Server,
                                SourceDatabase = sourceConnectionInfo.Database,
                                TargetServer   = targetConnectionInfo.Server,
                                TargetDatabase = targetConnectionInfo.Database
                            };

                            this.HandleError(schemaTransferException);
                        }

                        targetInterpreter.Feedback(FeedbackInfoType.Info, "End sync schema.");
                    }
                }
                #endregion

                #region Data sync
                if (!targetInterpreter.HasError && this.Option.GenerateScriptMode.HasFlag(GenerateScriptMode.Data) && sourceSchemaInfo.Tables.Count > 0)
                {
                    List <TableColumn> identityTableColumns = new List <TableColumn>();
                    if (generateIdentity)
                    {
                        identityTableColumns = targetSchemaInfo.TableColumns.Where(item => item.IsIdentity).ToList();
                    }

                    if (this.Option.PickupTable)
                    {
                        dataErrorProfile = DataTransferErrorProfileManager.GetProfile(sourceInterpreter.ConnectionInfo, targetInterpreter.ConnectionInfo);

                        if (dataErrorProfile != null)
                        {
                            sourceSchemaInfo.PickupTable = new Table()
                            {
                                Owner = schemaInfo.Tables.FirstOrDefault()?.Owner, Name = dataErrorProfile.SourceTableName
                            };
                        }
                    }

                    if (sourceInterpreter.Option.ScriptOutputMode.HasFlag(GenerateScriptOutputMode.WriteToFile))
                    {
                        sourceInterpreter.AppendScriptsToFile("", GenerateScriptMode.Data, true);
                    }

                    if (targetInterpreter.Option.ScriptOutputMode.HasFlag(GenerateScriptOutputMode.WriteToFile))
                    {
                        targetInterpreter.AppendScriptsToFile("", GenerateScriptMode.Data, true);
                    }

                    foreach (var item in identityTableColumns)
                    {
                        if (targetInterpreter.DatabaseType == DatabaseType.SqlServer)
                        {
                            await targetInterpreter.SetIdentityEnabled(dbConnection, item, false);
                        }
                    }

                    if (this.Option.ExecuteScriptOnTargetServer || targetInterpreter.Option.ScriptOutputMode.HasFlag(GenerateScriptOutputMode.WriteToFile))
                    {
                        sourceInterpreter.OnDataRead += async(table, columns, data, dataTable) =>
                        {
                            if (!this.hasError)
                            {
                                try
                                {
                                    StringBuilder sb = new StringBuilder();

                                    (Table Table, List <TableColumn> Columns)targetTableAndColumns = this.GetTargetTableColumns(targetSchemaInfo, this.Target.DbOwner, table, columns);

                                    if (targetTableAndColumns.Table == null || targetTableAndColumns.Columns == null)
                                    {
                                        return;
                                    }

                                    Dictionary <string, object> paramters = targetInterpreter.AppendDataScripts(sb, targetTableAndColumns.Table, targetTableAndColumns.Columns, new Dictionary <long, List <Dictionary <string, object> > >()
                                    {
                                        { 1, data }
                                    });

                                    script = sb.ToString().Trim().Trim(';');

                                    if (this.Option.ExecuteScriptOnTargetServer)
                                    {
                                        if (this.Option.BulkCopy && targetInterpreter.SupportBulkCopy)
                                        {
                                            await targetInterpreter.BulkCopyAsync(dbConnection, dataTable, table.Name);
                                        }
                                        else
                                        {
                                            await targetInterpreter.ExecuteNonQueryAsync(dbConnection, this.GetCommandInfo(script, paramters, this.transaction));
                                        }

                                        targetInterpreter.FeedbackInfo($"Table \"{table.Name}\":{data.Count} records transferred.");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    sourceInterpreter.CancelRequested = true;

                                    this.Rollback();

                                    ConnectionInfo sourceConnectionInfo = sourceInterpreter.ConnectionInfo;
                                    ConnectionInfo targetConnectionInfo = targetInterpreter.ConnectionInfo;

                                    DataTransferException dataTransferException = new DataTransferException(ex)
                                    {
                                        SourceServer   = sourceConnectionInfo.Server,
                                        SourceDatabase = sourceConnectionInfo.Database,
                                        SourceObject   = table.Name,
                                        TargetServer   = targetConnectionInfo.Server,
                                        TargetDatabase = targetConnectionInfo.Database,
                                        TargetObject   = table.Name
                                    };

                                    this.HandleError(dataTransferException);

                                    if (!this.Option.UseTransaction)
                                    {
                                        DataTransferErrorProfileManager.Save(new DataTransferErrorProfile
                                        {
                                            SourceServer    = sourceConnectionInfo.Server,
                                            SourceDatabase  = sourceConnectionInfo.Database,
                                            SourceTableName = table.Name,
                                            TargetServer    = targetConnectionInfo.Server,
                                            TargetDatabase  = targetConnectionInfo.Database,
                                            TargetTableName = table.Name
                                        });
                                    }
                                }
                            }
                        };
                    }

                    await sourceInterpreter.GenerateDataScriptsAsync(sourceSchemaInfo);

                    foreach (var item in identityTableColumns)
                    {
                        if (targetInterpreter.DatabaseType == DatabaseType.SqlServer)
                        {
                            await targetInterpreter.SetIdentityEnabled(dbConnection, item, true);
                        }
                    }
                }
                #endregion

                if (this.transaction != null && !this.cancelRequested)
                {
                    this.transaction.Commit();
                }

                this.isBusy = false;
            }

            if (dataErrorProfile != null && !this.hasError && !this.cancelRequested)
            {
                DataTransferErrorProfileManager.Remove(dataErrorProfile);
            }
        }
예제 #12
0
 public Task Convert(SchemaInfo schemaInfo = null)
 {
     return(this.InternalConvert(schemaInfo));
 }
예제 #13
0
        public override string GenerateSchemaScripts(SchemaInfo schemaInfo)
        {
            StringBuilder sb = new StringBuilder();

            #region User Defined Type
            foreach (UserDefinedType userDefinedType in schemaInfo.UserDefinedTypes)
            {
                this.FeedbackInfo($"Begin generate user defined type {userDefinedType.Name} script.");

                TableColumn column = new TableColumn()
                {
                    DataType = userDefinedType.Type, MaxLength = userDefinedType.MaxLength, Precision = userDefinedType.Precision, Scale = userDefinedType.Scale
                };
                string dataLength = this.GetColumnDataLength(column);

                sb.AppendLine($@"CREATE TYPE {GetQuotedString(userDefinedType.Owner)}.{GetQuotedString(userDefinedType.Name)} FROM {GetQuotedString(userDefinedType.Type)}{(dataLength==""? "": "("+dataLength+")")} {(userDefinedType.IsRequired? "NOT NULL":"NULL")};");

                this.FeedbackInfo($"End generate user defined type {userDefinedType.Name} script.");
            }

            sb.AppendLine("GO");

            #endregion

            foreach (Table table in schemaInfo.Tables)
            {
                this.FeedbackInfo($"Begin generate table {table.Name} script.");

                string tableName       = table.Name;
                string quotedTableName = this.GetQuotedTableName(table);
                IEnumerable <TableColumn> tableColumns = schemaInfo.Columns.Where(item => item.Owner == table.Owner && item.TableName == tableName).OrderBy(item => item.Order);

                bool hasBigDataType = tableColumns.Any(item => this.IsBigDataType(item));

                string primaryKey = "";

                IEnumerable <TablePrimaryKey> primaryKeys = schemaInfo.TablePrimaryKeys.Where(item => item.Owner == table.Owner && item.TableName == tableName);

                #region Primary Key
                if (Option.GenerateKey && primaryKeys.Count() > 0)
                {
                    primaryKey =
                        $@"
,CONSTRAINT {GetQuotedString(primaryKeys.First().KeyName)} PRIMARY KEY CLUSTERED 
(
{string.Join(Environment.NewLine, primaryKeys.Select(item => $"{GetQuotedString(item.ColumnName)} {(item.IsDesc ? "DESC" : "ASC")},")).TrimEnd(',')}
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]";
                }

                #endregion

                #region Create Table
                sb.Append(
                    $@"
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON

CREATE TABLE {quotedTableName}(
{string.Join("," + Environment.NewLine, tableColumns.Select(item => this.TranslateColumn(table, item) ))}{primaryKey}
) ON [PRIMARY]{(hasBigDataType ? " TEXTIMAGE_ON [PRIMARY]" : "")}");
                #endregion

                sb.AppendLine();

                #region Comment
                if (!string.IsNullOrEmpty(table.Comment))
                {
                    sb.AppendLine($"EXECUTE sp_addextendedproperty N'MS_Description',N'{ValueHelper.TransferSingleQuotation(table.Comment)}',N'SCHEMA',N'{table.Owner}',N'table',N'{tableName}',NULL,NULL;");
                }

                foreach (TableColumn column in tableColumns.Where(item => !string.IsNullOrEmpty(item.Comment)))
                {
                    sb.AppendLine($"EXECUTE sp_addextendedproperty N'MS_Description',N'{ValueHelper.TransferSingleQuotation(column.Comment)}',N'SCHEMA',N'{table.Owner}',N'table',N'{tableName}',N'column',N'{column.ColumnName}';");
                }
                #endregion

                #region Foreign Key
                if (Option.GenerateKey)
                {
                    IEnumerable <TableForeignKey> foreignKeys = schemaInfo.TableForeignKeys.Where(item => item.Owner == table.Owner && item.TableName == tableName);
                    if (foreignKeys.Count() > 0)
                    {
                        ILookup <string, TableForeignKey> foreignKeyLookup = foreignKeys.ToLookup(item => item.KeyName);

                        IEnumerable <string> keyNames = foreignKeyLookup.Select(item => item.Key);

                        foreach (string keyName in keyNames)
                        {
                            TableForeignKey tableForeignKey = foreignKeyLookup[keyName].First();

                            string columnNames         = string.Join(",", foreignKeyLookup[keyName].Select(item => $"[{item.ColumnName}]"));
                            string referenceColumnName = string.Join(",", foreignKeyLookup[keyName].Select(item => $"[{item.ReferencedColumnName}]"));

                            sb.Append(
                                $@"
ALTER TABLE {quotedTableName} WITH CHECK ADD CONSTRAINT [{keyName}] FOREIGN KEY({columnNames})
REFERENCES {GetQuotedString(table.Owner)}.{GetQuotedString(tableForeignKey.ReferencedTableName)} ({referenceColumnName})
");

                            if (tableForeignKey.UpdateCascade)
                            {
                                sb.AppendLine("ON UPDATE CASCADE");
                            }

                            if (tableForeignKey.DeleteCascade)
                            {
                                sb.AppendLine("ON DELETE CASCADE");
                            }

                            sb.AppendLine($"ALTER TABLE {quotedTableName} CHECK CONSTRAINT [{keyName}];");
                        }
                    }
                }
                #endregion

                #region Index
                if (Option.GenerateIndex)
                {
                    IEnumerable <TableIndex> indices = schemaInfo.TableIndices.Where(item => item.Owner == table.Owner && item.TableName == tableName).OrderBy(item => item.Order);
                    if (indices.Count() > 0)
                    {
                        sb.AppendLine();

                        List <string> indexColumns = new List <string>();
                        ILookup <string, TableIndex> indexLookup = indices.ToLookup(item => item.IndexName);
                        IEnumerable <string>         indexNames  = indexLookup.Select(item => item.Key);
                        foreach (string indexName in indexNames)
                        {
                            TableIndex tableIndex  = indexLookup[indexName].First();
                            string     columnNames = string.Join(",", indexLookup[indexName].Select(item => $"{GetQuotedString(item.ColumnName)} {(item.IsDesc ? "DESC" : "ASC")}"));

                            if (indexColumns.Contains(columnNames))
                            {
                                continue;
                            }
                            sb.AppendLine($"CREATE {(tableIndex.IsUnique ? "UNIQUE" : "")} INDEX {tableIndex.IndexName} ON {quotedTableName}({columnNames});");
                            if (!indexColumns.Contains(columnNames))
                            {
                                indexColumns.Add(columnNames);
                            }
                        }
                    }
                }
                #endregion

                #region Default Value
                if (Option.GenerateDefaultValue)
                {
                    IEnumerable <TableColumn> defaultValueColumns = schemaInfo.Columns.Where(item => item.Owner == table.Owner && item.TableName == tableName && !string.IsNullOrEmpty(item.DefaultValue));
                    foreach (TableColumn column in defaultValueColumns)
                    {
                        sb.AppendLine($"ALTER TABLE {quotedTableName} ADD CONSTRAINT {GetQuotedString($" DF_{tableName}_{column.ColumnName}")}  DEFAULT {column.DefaultValue} FOR [{column.ColumnName}];");
                    }
                }
                #endregion

                this.FeedbackInfo($"End generate table {table.Name} script.");
            }

            if (Option.ScriptOutputMode == GenerateScriptOutputMode.WriteToFile)
            {
                this.AppendScriptsToFile(sb.ToString(), GenerateScriptMode.Schema, true);
            }

            return(sb.ToString());
        }