protected virtual void Generate( Action <ModelBuilder> buildAction, MigrationOperation[] operation, MigrationsSqlGenerationOptions options) { var services = ContextOptions != null ? TestHelpers.CreateContextServices(CustomServices, ContextOptions) : TestHelpers.CreateContextServices(CustomServices); IModel model = null; if (buildAction != null) { var modelBuilder = TestHelpers.CreateConventionBuilder(); modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersion); buildAction(modelBuilder); model = modelBuilder.Model; var conventionSet = services.GetRequiredService <IConventionSetBuilder>().CreateConventionSet(); var typeMappingConvention = conventionSet.ModelFinalizingConventions.OfType <TypeMappingConvention>().FirstOrDefault(); typeMappingConvention.ProcessModelFinalizing(((IConventionModel)model).Builder, null); var relationalModelConvention = conventionSet.ModelFinalizedConventions.OfType <RelationalModelConvention>().First(); model = relationalModelConvention.ProcessModelFinalized((IConventionModel)model); } var batch = services.GetRequiredService <IMigrationsSqlGenerator>().Generate(operation, model, options); Sql = string.Join( "GO" + EOL + EOL, batch.Select(b => b.CommandText)); }
public IReadOnlyList <MigrationCommand> Generate( IReadOnlyList <MigrationOperation> operations, IModel?model = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { throw new(); }
private string[] GetMigrationCommandTexts( IReadOnlyList <MigrationOperation> migrationOperations, bool beginTexts, MigrationsSqlGenerationOptions options) => GetCustomCommands(migrationOperations) .Select(t => PrepareString(beginTexts ? t.Item1 : t.Item2, options)) .ToArray();
public override string GenerateScript( string fromMigration = null, string toMigration = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { var script = base.GenerateScript(fromMigration, toMigration, options); if (!options.HasFlag(MigrationsSqlGenerationOptions.Idempotent)) { return(script); } // Add helper stored procedures after database creation, but before applying migrations. // Remove them after all migrations have been apllied. var createScript = new StringBuilder(_historyRepository.GetCreateIfNotExistsScript()) .Append(_sqlGenerationHelper.BatchTerminator) .ToString(); var operations = GetIdempotentScriptMigrationOperations(fromMigration, toMigration); var builder = new StringBuilder(); if (script.StartsWith(createScript)) { script = script.Remove(0, createScript.Length); builder.Append(createScript); } builder.AppendJoin(string.Empty, GetMigrationCommandTexts(operations, true, options)); builder.Append(script); builder.AppendJoin(string.Empty, GetMigrationCommandTexts(operations, false, options)); return(builder.ToString()); }
protected virtual void Generate( Action <ModelBuilder> buildAction, MigrationOperation[] operation, MigrationsSqlGenerationOptions options, CharSetBehavior?charSetBehavior, [CanBeNull] CharSet charSet, MySqlSchemaNameTranslator schemaNameTranslator = null) { var optionsBuilder = new DbContextOptionsBuilder(ContextOptions); var mySqlOptionsBuilder = new MySqlDbContextOptionsBuilder(optionsBuilder); if (charSetBehavior != null) { mySqlOptionsBuilder.CharSetBehavior(charSetBehavior.Value); } if (charSet != null) { mySqlOptionsBuilder.CharSet(charSet); } if (schemaNameTranslator != null) { mySqlOptionsBuilder.SchemaBehavior(MySqlSchemaBehavior.Translate, schemaNameTranslator); } var contextOptions = optionsBuilder.Options; var services = ContextOptions != null ? TestHelpers.CreateContextServices(CustomServices, contextOptions) : TestHelpers.CreateContextServices(CustomServices); IModel model = null; if (buildAction != null) { var modelBuilder = TestHelpers.CreateConventionBuilder(); modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersion); buildAction(modelBuilder); model = modelBuilder.Model; var conventionSet = services.GetRequiredService <IConventionSetBuilder>().CreateConventionSet(); var typeMappingConvention = conventionSet.ModelFinalizingConventions.OfType <TypeMappingConvention>().FirstOrDefault(); typeMappingConvention.ProcessModelFinalizing(((IConventionModel)model).Builder, null); var relationalModelConvention = conventionSet.ModelFinalizedConventions.OfType <RelationalModelConvention>().First(); model = relationalModelConvention.ProcessModelFinalized((IConventionModel)model); } var batch = services.GetRequiredService <IMigrationsSqlGenerator>().Generate(operation, model, options); Sql = string.Join( EOL, batch.Select(b => b.CommandText)); }
/// <summary> /// Gets the commands that will create all tables from the model. /// </summary> /// <param name="options">The options to use when generating commands.</param> /// <returns>The generated commands.</returns> protected virtual IReadOnlyList <MigrationCommand> GetCreateTablesCommands( MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { var model = Dependencies.CurrentContext.Context.GetService <IDesignTimeModel>().Model; return(Dependencies.MigrationsSqlGenerator.Generate( Dependencies.ModelDiffer.GetDifferences(null, model.GetRelationalModel()), model, options)); }
protected virtual void Generate( Action <ModelBuilder> buildAction, Action <MigrationBuilder> migrateAction, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { var migrationBuilder = new MigrationBuilder(activeProvider: null); migrateAction(migrationBuilder); Generate(buildAction, migrationBuilder.Operations.ToArray(), options); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected virtual IReadOnlyList <MigrationCommand> GenerateUpSql( Migration migration, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { var insertCommand = _rawSqlCommandBuilder.Build( _historyRepository.GetInsertScript(new HistoryRow(migration.GetId(), ProductInfo.GetVersion()))); return(_migrationsSqlGenerator .Generate(migration.UpOperations, FinalizeModel(migration.TargetModel), options) .Concat(new[] { new MigrationCommand(insertCommand, _currentContext.Context, _commandLogger) }) .ToList()); }
protected override IReadOnlyList <MigrationCommand> GenerateUpSql( Migration migration, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { var commands = base.GenerateUpSql(migration, options); return(options.HasFlag(MigrationsSqlGenerationOptions.Script) && options.HasFlag(MigrationsSqlGenerationOptions.Idempotent) ? commands : WrapWithCustomCommands( migration.UpOperations, commands.ToList(), options)); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected virtual IReadOnlyList <MigrationCommand> GenerateDownSql( Migration migration, Migration?previousMigration, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { var deleteCommand = _rawSqlCommandBuilder.Build( _historyRepository.GetDeleteScript(migration.GetId())); return(_migrationsSqlGenerator .Generate( migration.DownOperations, previousMigration == null ? null : FinalizeModel(previousMigration.TargetModel), options) .Concat(new[] { new MigrationCommand(deleteCommand, _currentContext.Context, _commandLogger) }) .ToList()); }
/// <summary> /// Generates commands from a list of operations. /// </summary> /// <param name="operations"> The operations. </param> /// <param name="model"> The target model which may be <see langword="null" /> if the operations exist without a model. </param> /// <param name="options"> The options to use when generating commands. </param> /// <returns> The list of commands to be executed or scripted. </returns> public override IReadOnlyList <MigrationCommand> Generate( IReadOnlyList <MigrationOperation> operations, IModel model = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { _operations = operations; try { return(base.Generate(operations, model, options)); } finally { _operations = null; } }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual string ScriptMigration( [CanBeNull] string fromMigration, [CanBeNull] string toMigration, MigrationsSqlGenerationOptions options, [CanBeNull] string contextType) { using var context = _contextOperations.CreateContext(contextType); var services = _servicesBuilder.Build(context); EnsureServices(services); var migrator = services.GetRequiredService <IMigrator>(); return(migrator.GenerateScript(fromMigration, toMigration, options)); }
private string PrepareString(string str, MigrationsSqlGenerationOptions options) { str = options.HasFlag(MigrationsSqlGenerationOptions.Script) ? str : CleanUpScriptSpecificPseudoStatements(str); str = str .Replace("\r", string.Empty) .Replace("\n", Environment.NewLine); str += options.HasFlag(MigrationsSqlGenerationOptions.Script) ? Environment.NewLine + ( options.HasFlag(MigrationsSqlGenerationOptions.Idempotent) ? Environment.NewLine : string.Empty) : string.Empty; return(str); }
private IReadOnlyList <MigrationCommand> WrapWithCustomCommands( IReadOnlyList <MigrationOperation> migrationOperations, List <MigrationCommand> migrationCommands, MigrationsSqlGenerationOptions options) { var beginCommandTexts = GetMigrationCommandTexts(migrationOperations, true, options); var endCommandTexts = GetMigrationCommandTexts(migrationOperations, false, options); migrationCommands.InsertRange(0, beginCommandTexts.Select(t => new MigrationCommand( _rawSqlCommandBuilder.Build(t), _currentContext.Context, _commandLogger))); migrationCommands.AddRange(endCommandTexts.Select(t => new MigrationCommand( _rawSqlCommandBuilder.Build(t), _currentContext.Context, _commandLogger))); return(migrationCommands); }
public void Alter_column_change_serial_to_identity_idempotent(MigrationsSqlGenerationOptions options) { Generate( modelBuilder => { modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "3.1.0"); modelBuilder.Entity <Person>().Property <int>("Id").UseSerialColumn(); }, new[] { new AlterColumnOperation { Table = "Person", Name = "Id", ClrType = typeof(int), [NpgsqlAnnotationNames.ValueGenerationStrategy] = NpgsqlValueGenerationStrategy.IdentityByDefaultColumn, OldColumn = new AddColumnOperation { Table = "Person", Name = "Id", ClrType = typeof(int), [NpgsqlAnnotationNames.ValueGenerationStrategy] = NpgsqlValueGenerationStrategy.SerialColumn, } } }, options); AssertSql( $@"ALTER SEQUENCE ""Person_Id_seq"" RENAME TO ""Person_Id_old_seq""; ALTER TABLE ""Person"" ALTER COLUMN ""Id"" DROP DEFAULT; ALTER TABLE ""Person"" ALTER COLUMN ""Id"" ADD GENERATED BY DEFAULT AS IDENTITY; {(options == MigrationsSqlGenerationOptions.Idempotent ? "PERFORM" : "SELECT")} * FROM setval('""Person_Id_seq""', nextval('""Person_Id_old_seq""'), false); DROP SEQUENCE ""Person_Id_old_seq""; "); }
public string GenerateScript(string fromMigration = null, string toMigration = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { return(_context.Database.GenerateCreateScript()); }
public virtual void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder) { var identitySequenceName = CreateSequenceTriggerSequenceName(columnName, tableName, schemaName); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.Append("SET TERM "); builder.Append(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); builder.AppendLine(_sqlGenerationHelper.StatementTerminator); builder.EndCommand(); } builder.AppendLine("EXECUTE BLOCK"); builder.AppendLine("AS"); builder.AppendLine("BEGIN"); builder.IncrementIndent(); builder.Append("if (not exists(select 1 from rdb$generators where rdb$generator_name = '"); builder.Append(identitySequenceName); builder.Append("')) then"); builder.AppendLine(); builder.AppendLine("begin"); builder.IncrementIndent(); builder.Append("execute statement 'create sequence "); builder.Append(identitySequenceName); builder.Append("'"); builder.Append(_sqlGenerationHelper.StatementTerminator); builder.AppendLine(); builder.DecrementIndent(); builder.AppendLine("end"); builder.DecrementIndent(); builder.Append("END"); builder.AppendLine(); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); } else { builder.AppendLine(_sqlGenerationHelper.StatementTerminator); } builder.EndCommand(); builder.Append("CREATE TRIGGER "); builder.Append(_sqlGenerationHelper.DelimitIdentifier(CreateSequenceTriggerName(columnName, tableName, schemaName))); builder.Append(" ACTIVE BEFORE INSERT ON "); builder.Append(_sqlGenerationHelper.DelimitIdentifier(tableName, schemaName)); builder.AppendLine(); builder.AppendLine("AS"); builder.AppendLine("BEGIN"); builder.IncrementIndent(); builder.Append("if (new."); builder.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)); builder.Append(" is null) then"); builder.AppendLine(); builder.AppendLine("begin"); builder.IncrementIndent(); builder.Append("new."); builder.Append(_sqlGenerationHelper.DelimitIdentifier(columnName)); builder.Append(" = next value for "); builder.Append(identitySequenceName); builder.Append(_sqlGenerationHelper.StatementTerminator); builder.AppendLine(); builder.DecrementIndent(); builder.AppendLine("end"); builder.DecrementIndent(); builder.Append("END"); builder.AppendLine(); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); } else { builder.AppendLine(_sqlGenerationHelper.StatementTerminator); } builder.EndCommand(); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.Append("SET TERM "); builder.Append(_sqlGenerationHelper.StatementTerminator); builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); builder.EndCommand(); } }
/// <summary> /// Generates commands from a list of operations. /// </summary> /// <param name="operations">The operations.</param> /// <param name="model">The target model which may be <see langword="null" /> if the operations exist without a model.</param> /// <param name="options">The options to use when generating commands.</param> /// <returns>The list of commands to be executed or scripted.</returns> public override IReadOnlyList <MigrationCommand> Generate( IReadOnlyList <MigrationOperation> operations, IModel?model = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) => base.Generate(RewriteOperations(operations, model), model, options);
/// <summary> /// Gets the commands that will create all tables from the model. /// </summary> /// <param name="options"> The options to use when generating commands. </param> /// <returns> The generated commands. </returns> protected virtual IReadOnlyList <MigrationCommand> GetCreateTablesCommands( MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) => Dependencies.MigrationsSqlGenerator.Generate( Dependencies.ModelDiffer.GetDifferences(null, Dependencies.Model.GetRelationalModel()), Dependencies.Model, options);
protected override void Generate( Action <ModelBuilder> buildAction, MigrationOperation[] operation, MigrationsSqlGenerationOptions options) => Generate(buildAction, operation, options, null, null);
async Task <IReadOnlyList <MigrationCommand> > Generate(IReadOnlyList <MigrationOperation> operations, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { await using (var db = await GetDbContext <FbTestDbContext>()) { var generator = db.GetService <IMigrationsSqlGenerator>(); return(generator.Generate(operations, db.Model, options)); } }
public string GenerateScript( string fromMigration = null, string toMigration = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) => throw new NotImplementedException();
public virtual void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder) { var triggerName = CreateSequenceTriggerName(columnName, tableName, schemaName); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.Append("SET TERM "); builder.Append(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); builder.AppendLine(_sqlGenerationHelper.StatementTerminator); builder.EndCommand(); } builder.AppendLine("EXECUTE BLOCK"); builder.AppendLine("AS"); builder.AppendLine("BEGIN"); builder.IncrementIndent(); builder.Append("if (exists(select 1 from rdb$triggers where rdb$trigger_name = '"); builder.Append(triggerName); builder.Append("')) then"); builder.AppendLine(); builder.AppendLine("begin"); builder.IncrementIndent(); builder.Append("execute statement 'drop trigger "); builder.Append(_sqlGenerationHelper.DelimitIdentifier(triggerName)); builder.Append("'"); builder.Append(_sqlGenerationHelper.StatementTerminator); builder.AppendLine(); builder.DecrementIndent(); builder.AppendLine("end"); builder.DecrementIndent(); builder.Append("END"); builder.AppendLine(); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); } else { builder.AppendLine(_sqlGenerationHelper.StatementTerminator); } builder.EndCommand(); if (options.HasFlag(MigrationsSqlGenerationOptions.Script)) { builder.Append("SET TERM "); builder.Append(_sqlGenerationHelper.StatementTerminator); builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator); builder.EndCommand(); } }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual string GenerateScript( string fromMigration = null, string toMigration = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { options |= MigrationsSqlGenerationOptions.Script; var idempotent = options.HasFlag(MigrationsSqlGenerationOptions.Idempotent); var noTransactions = options.HasFlag(MigrationsSqlGenerationOptions.NoTransactions); IEnumerable <string> appliedMigrations; if (string.IsNullOrEmpty(fromMigration) || fromMigration == Migration.InitialDatabase) { appliedMigrations = Enumerable.Empty <string>(); } else { var fromMigrationId = _migrationsAssembly.GetMigrationId(fromMigration); appliedMigrations = _migrationsAssembly.Migrations .Where(t => string.Compare(t.Key, fromMigrationId, StringComparison.OrdinalIgnoreCase) <= 0) .Select(t => t.Key); } PopulateMigrations( appliedMigrations, toMigration, out var migrationsToApply, out var migrationsToRevert, out var actualTargetMigration); var builder = new IndentedStringBuilder(); if (fromMigration == Migration.InitialDatabase || string.IsNullOrEmpty(fromMigration)) { builder .Append(_historyRepository.GetCreateIfNotExistsScript()) .Append(_sqlGenerationHelper.BatchTerminator); } var transactionStarted = false; for (var i = 0; i < migrationsToRevert.Count; i++) { var migration = migrationsToRevert[i]; var previousMigration = i != migrationsToRevert.Count - 1 ? migrationsToRevert[i + 1] : actualTargetMigration; _logger.MigrationGeneratingDownScript(this, migration, fromMigration, toMigration, idempotent); foreach (var command in GenerateDownSql(migration, previousMigration, options)) { if (!noTransactions) { if (!transactionStarted && !command.TransactionSuppressed) { builder .AppendLine(_sqlGenerationHelper.StartTransactionStatement) .Append(_sqlGenerationHelper.BatchTerminator); transactionStarted = true; } if (transactionStarted && command.TransactionSuppressed) { builder .AppendLine(_sqlGenerationHelper.CommitTransactionStatement) .Append(_sqlGenerationHelper.BatchTerminator); transactionStarted = false; } } if (idempotent) { builder.AppendLine(_historyRepository.GetBeginIfExistsScript(migration.GetId())); using (builder.Indent()) { builder.AppendLines(command.CommandText); } builder.Append(_historyRepository.GetEndIfScript()); } else { builder.Append(command.CommandText); } builder.Append(_sqlGenerationHelper.BatchTerminator); } if (!noTransactions && transactionStarted) { builder .AppendLine(_sqlGenerationHelper.CommitTransactionStatement) .Append(_sqlGenerationHelper.BatchTerminator); transactionStarted = false; } } foreach (var migration in migrationsToApply) { _logger.MigrationGeneratingUpScript(this, migration, fromMigration, toMigration, idempotent); foreach (var command in GenerateUpSql(migration, options)) { if (!noTransactions) { if (!transactionStarted && !command.TransactionSuppressed) { builder .AppendLine(_sqlGenerationHelper.StartTransactionStatement) .Append(_sqlGenerationHelper.BatchTerminator); transactionStarted = true; } if (transactionStarted && command.TransactionSuppressed) { builder .AppendLine(_sqlGenerationHelper.CommitTransactionStatement) .Append(_sqlGenerationHelper.BatchTerminator); transactionStarted = false; } } if (idempotent) { builder.AppendLine(_historyRepository.GetBeginIfNotExistsScript(migration.GetId())); using (builder.Indent()) { builder.AppendLines(command.CommandText); } builder.Append(_historyRepository.GetEndIfScript()); } else { builder.Append(command.CommandText); } builder.Append(_sqlGenerationHelper.BatchTerminator); } if (!noTransactions && transactionStarted) { builder .AppendLine(_sqlGenerationHelper.CommitTransactionStatement) .Append(_sqlGenerationHelper.BatchTerminator); transactionStarted = false; } } return(builder.ToString()); }
public string GenerateScript(string fromMigration = null, string toMigration = null, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) { return(CurrentTemporalTableMigrator.GenerateScript(fromMigration, toMigration, options)); }