using System.Data; using Bit.Core.Enums; using Bit.Infrastructure.EntityFramework.Repositories; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using MySqlConnector; using Npgsql; namespace Bit.Infrastructure.IntegrationTest.Services; /// /// An implementation of for testing Entity Framework migrations. /// This service applies a specific migration and manages the migration history /// to ensure that the migration is tested in isolation. It supports MySQL, Postgres, and SQLite. /// public class EfMigrationTesterService : IMigrationTesterService { private readonly DatabaseContext _databaseContext; private readonly SupportedDatabaseProviders _databaseType; private readonly string _migrationName; public EfMigrationTesterService( DatabaseContext databaseContext, SupportedDatabaseProviders databaseType, string migrationName) { _databaseContext = databaseContext; _databaseType = databaseType; _migrationName = migrationName; } public void ApplyMigration() { // Delete the migration history to ensure the migration is applied DeleteMigrationHistory(); var migrator = _databaseContext.GetService(); migrator.Migrate(_migrationName); } /// /// Deletes the migration history for the specified migration name. /// private void DeleteMigrationHistory() { var deleteCommand = "DELETE FROM __EFMigrationsHistory WHERE MigrationId LIKE @migrationName"; IDbDataParameter? parameter; switch (_databaseType) { case SupportedDatabaseProviders.MySql: parameter = new MySqlParameter("@migrationName", "%" + _migrationName); break; case SupportedDatabaseProviders.Postgres: deleteCommand = "DELETE FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" LIKE @migrationName"; parameter = new NpgsqlParameter("@migrationName", "%" + _migrationName); break; case SupportedDatabaseProviders.Sqlite: parameter = new SqliteParameter("@migrationName", "%" + _migrationName); break; default: throw new InvalidOperationException($"Unsupported database type: {_databaseType}"); } _databaseContext.Database.ExecuteSqlRaw(deleteCommand, parameter); } }