Example #1
0
        /// <summary>
        /// Initiates a migration operation to the target migration version.
        /// </summary>
        /// <param name="plugin">The plugin whose migrations should be run.</param>
        /// <param name="targetMigration">The target migration.</param>
        public virtual void Migrate(EntityPlugin plugin, string targetMigration = null)
        {
            Logger.LogInformation(LoggingEvents.MigratingId, LoggingEvents.Migrating, plugin.Identifier, Connection.DbConnection.Database, Connection.DbConnection.DataSource);

            //
            // Verify the history table exists and if not create it.
            //
            if (!PluginHistoryRepository.Exists())
            {
                var command = RawSqlCommandBuilder.Build(PluginHistoryRepository.GetCreateScript());

                var query = new RelationalCommandParameterObject(Connection, null, null, CurrentContext.Context, CommandLogger);

                command.ExecuteNonQuery(query);
            }

            //
            // Get all the command lists to be executed.
            //
            var commandLists = GetMigrationCommandLists(
                plugin,
                PluginHistoryRepository.GetAppliedMigrations(plugin),
                targetMigration);

            //
            // Execute each command list in order.
            //
            foreach (var commandList in commandLists)
            {
                MigrationCommandExecutor.ExecuteNonQuery(commandList(), Connection);
            }
        }
Example #2
0
        public async Task Executes_commands_in_order_regardless_of_transaction_suppression(bool async)
        {
            var fakeConnection = CreateConnection();
            var logger         = new FakeRelationalCommandDiagnosticsLogger();

            var commandList = new List <MigrationCommand>
            {
                new(CreateRelationalCommand(commandText: "First"), null, logger),
                new(CreateRelationalCommand(commandText: "Second"), null, logger, transactionSuppressed : true),
                new(CreateRelationalCommand(commandText : "Third"), null, logger)
            };

            var migrationCommandExecutor = new MigrationCommandExecutor();

            if (async)
            {
                await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection);
            }
            else
            {
                migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection);
            }

            Assert.Equal(1, fakeConnection.DbConnections.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].OpenCount);
            Assert.Equal(1, fakeConnection.DbConnections[0].CloseCount);

            Assert.Equal(2, fakeConnection.DbConnections[0].DbTransactions.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions[0].CommitCount);
            Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions[0].RollbackCount);
            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions[1].CommitCount);
            Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions[1].RollbackCount);

            Assert.Equal(3, fakeConnection.DbConnections[0].DbCommands.Count);

            var command = fakeConnection.DbConnections[0].DbCommands[0];

            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[0],
                command.Transaction);
            Assert.Equal(
                "First",
                command.CommandText);

            command = fakeConnection.DbConnections[0].DbCommands[1];

            Assert.Null(command.Transaction);
            Assert.Equal(
                "Second",
                command.CommandText);

            command = fakeConnection.DbConnections[0].DbCommands[2];

            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[1],
                command.Transaction);
            Assert.Equal(
                "Third",
                command.CommandText);
        }
Example #3
0
        public async Task Executes_migration_commands_with_transaction_suppressed_outside_of_transaction(bool async)
        {
            var fakeConnection = CreateConnection();
            var logger         = new FakeRelationalCommandDiagnosticsLogger();

            var commandList = new List <MigrationCommand>
            {
                new(CreateRelationalCommand(), null, logger, transactionSuppressed : true),
                new(CreateRelationalCommand(), null, logger, transactionSuppressed : true)
            };

            var migrationCommandExecutor = new MigrationCommandExecutor();

            if (async)
            {
                await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection);
            }
            else
            {
                migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection);
            }

            Assert.Equal(1, fakeConnection.DbConnections.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].OpenCount);
            Assert.Equal(1, fakeConnection.DbConnections[0].CloseCount);

            Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions.Count);

            Assert.Equal(2, fakeConnection.DbConnections[0].DbCommands.Count);
            Assert.Null(fakeConnection.DbConnections[0].DbCommands[0].Transaction);
            Assert.Null(fakeConnection.DbConnections[0].DbCommands[1].Transaction);
        }
Example #4
0
        public override void Create()
        {
            using (var masterConnection = _connection.CreateMasterConnection())
            {
                MigrationCommandExecutor
                .ExecuteNonQuery(CreateCreateOperations(), masterConnection);

                ClearPool();
            }
        }
Example #5
0
        public override async Task CreateAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            using (var masterConnection = _connection.CreateMasterConnection())
            {
                await MigrationCommandExecutor
                .ExecuteNonQueryAsync(CreateCreateOperations(), masterConnection, cancellationToken);

                ClearPool();
            }
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public override void Delete()
        {
            ClearAllPools();

            using (var masterConnection = _connection.CreateMasterConnection())
            {
                MigrationCommandExecutor
                .ExecuteNonQuery(CreateDropCommands(), masterConnection);
            }
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public override async Task DeleteAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            ClearAllPools();

            using (var masterConnection = _connection.CreateMasterConnection())
            {
                await MigrationCommandExecutor
                .ExecuteNonQueryAsync(CreateDropCommands(), masterConnection, cancellationToken);
            }
        }
Example #8
0
        public async Task DeleteAsync(MyCatDatabaseHost node, CancellationToken cancellationToken = default(CancellationToken))
        {
            ClearAllPools();

            using (var masterConnection = _connection.CreateMasterConnection(node))
            {
                await MigrationCommandExecutor
                .ExecuteNonQueryAsync(CreateDropCommands(), masterConnection, cancellationToken);
            }
        }
Example #9
0
        public void Delete(MyCatDatabaseHost node)
        {
            ClearAllPools();

            using (var masterConnection = _connection.CreateMasterConnection(node))
            {
                MigrationCommandExecutor
                .ExecuteNonQuery(CreateDropCommands(), masterConnection);
            }
        }
Example #10
0
        public async Task CreateAsync(MyCatDatabaseHost node, CancellationToken cancellationToken = default(CancellationToken))
        {
            using (var masterConnection = _connection.CreateMasterConnection(node))
            {
                await MigrationCommandExecutor
                .ExecuteNonQueryAsync(CreateCreateOperations(node), masterConnection, cancellationToken);

                ClearPool();
            }

            await ExistsAsync(_connection.CreateNodeConnection(node), retryOnNotExists : true, cancellationToken : cancellationToken);
        }
Example #11
0
        public void Create(MyCatDatabaseHost node)
        {
            using (var masterConnection = _connection.CreateMasterConnection(node))
            {
                var cmd = CreateCreateOperations(node);
                MigrationCommandExecutor
                .ExecuteNonQuery(cmd, masterConnection);

                ClearPool();
            }

            Exists(_connection.CreateNodeConnection(node), retryOnNotExists: false);
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public override void Create()
        {
            using (var masterConnection = _connection.CreateMasterConnection())
            {
                var cmd = CreateCreateOperations();
                MigrationCommandExecutor
                .ExecuteNonQuery(cmd, masterConnection);

                ClearPool();
            }

            Exists(retryOnNotExists: false);
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public override async Task CreateAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            using (var masterConnection = _connection.CreateMasterConnection())
            {
                await MigrationCommandExecutor
                .ExecuteNonQueryAsync(CreateCreateOperations(), masterConnection, cancellationToken)
                .ConfigureAwait(false);

                ClearPool();
            }

            await ExistsAsync(retryOnNotExists : true, cancellationToken : cancellationToken).ConfigureAwait(false);
        }
    public async Task Executes_transaction_suppressed_migration_commands_in_user_transaction(bool async)
    {
        var fakeConnection = CreateConnection();
        var logger         = new FakeRelationalCommandDiagnosticsLogger();

        var commandList = new List <MigrationCommand>
        {
            new(CreateRelationalCommand(), null, logger), new(CreateRelationalCommand(), null, logger, transactionSuppressed : true)
        };

        var migrationCommandExecutor = new MigrationCommandExecutor();

        IDbContextTransaction tx;

        using (tx = fakeConnection.BeginTransaction())
        {
            if (async)
            {
                Assert.Equal(
                    RelationalStrings.TransactionSuppressedMigrationInUserTransaction,
                    (await Assert.ThrowsAsync <NotSupportedException>(
                         async()
                         => await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection))).Message);
            }
            else
            {
                Assert.Equal(
                    RelationalStrings.TransactionSuppressedMigrationInUserTransaction,
                    Assert.Throws <NotSupportedException>(
                        ()
                        => migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection)).Message);
            }

            tx.Rollback();
        }

        Assert.Equal(1, fakeConnection.DbConnections.Count);
        Assert.Equal(1, fakeConnection.DbConnections[0].OpenCount);
        Assert.Equal(1, fakeConnection.DbConnections[0].CloseCount);

        Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions.Count);
        Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions[0].CommitCount);
        Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions[0].RollbackCount);

        Assert.Equal(0, fakeConnection.DbConnections[0].DbCommands.Count);
        Assert.Same(
            tx.GetDbTransaction(),
            fakeConnection.DbConnections[0].DbTransactions[0]);
    }
Example #15
0
        public async Task Executes_migration_commands_in_user_transaction(bool async)
        {
            var fakeConnection = CreateConnection();
            var logger         = new FakeRelationalCommandDiagnosticsLogger();

            var commandList = new List <MigrationCommand>
            {
                new(CreateRelationalCommand(), null, logger),
                new(CreateRelationalCommand(), null, logger)
            };

            var migrationCommandExecutor = new MigrationCommandExecutor();

            IDbContextTransaction tx;

            using (tx = fakeConnection.BeginTransaction())
            {
                if (async)
                {
                    await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection);
                }
                else
                {
                    migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection);
                }

                tx.Commit();
            }

            Assert.Equal(1, fakeConnection.DbConnections.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].OpenCount);
            Assert.Equal(1, fakeConnection.DbConnections[0].CloseCount);

            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions[0].CommitCount);
            Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions[0].RollbackCount);

            Assert.Equal(2, fakeConnection.DbConnections[0].DbCommands.Count);
            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[0],
                fakeConnection.DbConnections[0].DbCommands[0].Transaction);
            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[0],
                fakeConnection.DbConnections[0].DbCommands[1].Transaction);
            Assert.Same(
                tx.GetDbTransaction(),
                fakeConnection.DbConnections[0].DbTransactions[0]);
        }
        public async Task Disposes_transaction_on_exception(bool async)
        {
            var fakeDbConnection =
                new FakeDbConnection(
                    ConnectionString,
                    new FakeCommandExecutor(
                        executeNonQuery: c => throw new InvalidOperationException(),
                        executeNonQueryAsync: (c, ct) => throw new InvalidOperationException()));

            var fakeConnection =
                CreateConnection(
                    CreateOptions(
                        new FakeRelationalOptionsExtension().WithConnection(fakeDbConnection)));

            var logger = new FakeDiagnosticsLogger <DbLoggerCategory.Database.Command>();

            var commandList = new List <MigrationCommand>
            {
                new MigrationCommand(CreateRelationalCommand(), null, logger)
            };

            var migrationCommandExecutor = new MigrationCommandExecutor();

            if (async)
            {
                await Assert.ThrowsAsync <InvalidOperationException>(
                    async()
                    => await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection));
            }
            else
            {
                Assert.Throws <InvalidOperationException>(
                    ()
                    => migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection));
            }

            Assert.Equal(1, fakeDbConnection.OpenCount);
            Assert.Equal(1, fakeDbConnection.CloseCount);

            Assert.Equal(1, fakeDbConnection.DbTransactions.Count);
            Assert.Equal(1, fakeDbConnection.DbTransactions[0].DisposeCount);
            Assert.Equal(0, fakeDbConnection.DbTransactions[0].CommitCount);
            Assert.Equal(0, fakeDbConnection.DbTransactions[0].RollbackCount);
        }
        public override async Task CreateAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            using (var masterConnection = _connection.CreateMasterConnection())
            {
                try
                {
                    await MigrationCommandExecutor
                    .ExecuteNonQueryAsync(CreateCreateOperations(), masterConnection, cancellationToken);
                }
                catch (PostgresException e) when(
                    e.SqlState == "23505" && e.TableName == "pg_database_datname_index"
                    )
                {
                    // This occurs when two connections are trying to create the same database concurrently
                    // (happens in the tests). Simply ignore the error.
                }

                ClearPool();
            }
        }
        public override void CreateTables()
        {
            var operations = _modelDiffer.GetDifferences(null, Model);
            var commands   = _migrationsSqlGenerator.Generate(operations, Model);

            // Adding a PostgreSQL extension might define new types (e.g. hstore), which we
            // Npgsql to reload
            var reloadTypes = operations.Any(o => o is AlterDatabaseOperation && PostgresExtension.GetPostgresExtensions(o).Any());

            MigrationCommandExecutor.ExecuteNonQuery(commands, Connection);

            if (reloadTypes)
            {
                var npgsqlConn = (NpgsqlConnection)Connection.DbConnection;
                if (npgsqlConn.FullState == ConnectionState.Open)
                {
                    npgsqlConn.ReloadTypes();
                }
            }
        }
        public override async Task CreateTablesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            var operations = _modelDiffer.GetDifferences(null, Model);
            var commands   = _migrationsSqlGenerator.Generate(operations, Model);

            // Adding a PostgreSQL extension might define new types (e.g. hstore), which we
            // Npgsql to reload
            var reloadTypes = operations.Any(o => o is NpgsqlCreatePostgresExtensionOperation);

            await MigrationCommandExecutor.ExecuteNonQueryAsync(commands, Connection, cancellationToken);

            // TODO: Not async
            if (reloadTypes)
            {
                var npgsqlConn = (NpgsqlConnection)Connection.DbConnection;
                if (npgsqlConn.FullState == ConnectionState.Open)
                {
                    npgsqlConn.ReloadTypes();
                }
            }
        }
Example #20
0
        public async Task Executes_migration_commands_in_same_transaction(bool async)
        {
            var fakeConnection = CreateConnection();
            var logger         = new FakeDiagnosticsLogger <DbLoggerCategory.Database.Command>();

            var commandList = new List <MigrationCommand>
            {
                new MigrationCommand(CreateRelationalCommand(), null, logger),
                new MigrationCommand(CreateRelationalCommand(), null, logger)
            };

            var migrationCommandExecutor = new MigrationCommandExecutor();

            if (async)
            {
                await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection);
            }
            else
            {
                migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection);
            }

            Assert.Equal(1, fakeConnection.DbConnections.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].OpenCount);
            Assert.Equal(1, fakeConnection.DbConnections[0].CloseCount);

            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions[0].CommitCount);
            Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions[0].RollbackCount);

            Assert.Equal(2, fakeConnection.DbConnections[0].DbCommands.Count);
            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[0],
                fakeConnection.DbConnections[0].DbCommands[0].Transaction);
            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[0],
                fakeConnection.DbConnections[0].DbCommands[1].Transaction);
        }
Example #21
0
        public async Task Begins_new_transaction_when_transaction_nolonger_suppressed(bool async)
        {
            var fakeConnection = CreateConnection();
            var logger         = new FakeRelationalCommandDiagnosticsLogger();

            var commandList = new List <MigrationCommand>
            {
                new(CreateRelationalCommand(), null, logger, transactionSuppressed : true),
                new(CreateRelationalCommand(), null, logger)
            };

            var migrationCommandExecutor = new MigrationCommandExecutor();

            if (async)
            {
                await migrationCommandExecutor.ExecuteNonQueryAsync(commandList, fakeConnection);
            }
            else
            {
                migrationCommandExecutor.ExecuteNonQuery(commandList, fakeConnection);
            }

            Assert.Equal(1, fakeConnection.DbConnections.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].OpenCount);
            Assert.Equal(1, fakeConnection.DbConnections[0].CloseCount);

            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions.Count);
            Assert.Equal(1, fakeConnection.DbConnections[0].DbTransactions[0].CommitCount);
            Assert.Equal(0, fakeConnection.DbConnections[0].DbTransactions[0].RollbackCount);

            Assert.Equal(2, fakeConnection.DbConnections[0].DbCommands.Count);
            Assert.Null(
                fakeConnection.DbConnections[0].DbCommands[0].Transaction);
            Assert.Same(
                fakeConnection.DbConnections[0].DbTransactions[0],
                fakeConnection.DbConnections[0].DbCommands[1].Transaction);
        }
Example #22
0
 public void CreateTables(MyCatDatabaseHost node)
 {
     MigrationCommandExecutor.ExecuteNonQuery(GetCreateTablesCommands(), _connection.CreateNodeConnection(node));
 }
Example #23
0
 public async Task CreateTablesAsync(MyCatDatabaseHost node, CancellationToken cancellationToken = default(CancellationToken))
 {
     await MigrationCommandExecutor.ExecuteNonQueryAsync(GetCreateTablesCommands(), _connection.CreateNodeConnection(node), cancellationToken);
 }
Example #24
0
 /// <summary>
 ///     Creates all tables for the current model in the database. No attempt is made
 ///     to incrementally update the schema. It is assumed that none of the tables exist in the database.
 /// </summary>
 public virtual void CreateTables()
 => MigrationCommandExecutor.ExecuteNonQuery(GetCreateTablesCommands(), Connection);
Example #25
0
 /// <summary>
 ///     Asynchronously creates all tables for the current model in the database. No attempt is made
 ///     to incrementally update the schema. It is assumed that none of the tables exist in the database.
 /// </summary>
 /// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
 /// <returns>
 ///     A task that represents the asynchronous operation.
 /// </returns>
 public virtual async Task CreateTablesAsync(CancellationToken cancellationToken = default(CancellationToken))
 => await MigrationCommandExecutor.ExecuteNonQueryAsync(GetCreateTablesCommands(), Connection, cancellationToken);