How to add a new code-first migration with a newly-generated database?

前端 未结 3 2171
花落未央
花落未央 2021-02-11 05:09

I\'ve enabled code-first migrations on my entity framework project, and have added several migrations which do things like rename tables. However, I have now deleted the databa

3条回答
  •  青春惊慌失措
    2021-02-11 05:53

    This implementation does not need to manually maintain records to be inserted to __MigrationHistory. Migrations are determined from assembly specified.

    Maybe this helps.

    My thanks goes to @Jez for initial idea.

    /// 
    /// An implementation of IDatabaseInitializer that will:
    /// 1. recreate database only if the database does not exist 
    /// 2. actualize __MigrationHistory to match current model state (i.e. latest migration)
    /// 
    /// The type of the context.
    public class CreateDatabaseIfNotExistsAndMigrateToLatest : CreateDatabaseIfNotExists
        where TContext : DbContext
    {
        private readonly Assembly migrationsAssembly;
    
        /// 
        /// Gets the migration metadata for types retrieved from . Types must implement .
        /// 
        /// The assembly.
        /// 
        private static IEnumerable GetMigrationMetadata(Assembly assembly)
        {
            var types = assembly.GetTypes().Where(t => typeof(IMigrationMetadata).IsAssignableFrom(t));
            var migrationMetadata = new List();
            foreach (var type in types)
            {
                migrationMetadata.Add(
                    (IMigrationMetadata)Activator.CreateInstance(type));
            }
    
            return migrationMetadata.OrderBy(m => m.Id);
        }
    
        /// 
        /// Gets the provider manifest token.
        /// 
        /// The db.
        /// 
        private static string GetProviderManifestToken(TContext db)
        {
            var connection = db.Database.Connection;
            var token = DbProviderServices.GetProviderServices(connection).GetProviderManifestToken(connection);
    
            return token;
        }
    
        /// 
        /// Gets the migration SQL generator. Currently it is .
        /// 
        /// 
        private static MigrationSqlGenerator GetMigrationSqlGenerator()
        {
            return new SqlServerMigrationSqlGenerator();
        }
    
        /// 
        /// Creates the operation for inserting into migration history. Operation is created for one .
        /// 
        /// The migration metadatum.
        /// 
        private static InsertHistoryOperation CreateInsertHistoryOperation(IMigrationMetadata migrationMetadatum)
        {
            var model = Convert.FromBase64String(migrationMetadatum.Target);
    
            var op = new InsertHistoryOperation(
                "__MigrationHistory",
                migrationMetadatum.Id,
                model,
                null);
    
            return op;
        }
    
        /// 
        /// Generates the SQL statements for inserting migration into history table.
        /// 
        /// The generator.
        /// The operation.
        /// The token.
        /// 
        private static IEnumerable GenerateInsertHistoryStatements(
            MigrationSqlGenerator generator,
            InsertHistoryOperation op,
            string token)
        {
            return generator.Generate(new[] { op }, token);
        }
    
        /// 
        /// Runs the SQL statements on database specified by  ().
        /// 
        /// The statements.
        /// The db.
        private static void RunSqlStatements(IEnumerable statements, TContext db)
        {
            foreach (var statement in statements)
            {
                db.Database.ExecuteSqlCommand(statement.Sql);
            }
        }
    
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The migrations assembly.
        public CreateDatabaseIfNotExistsAndMigrateToLatest(Assembly migrationsAssembly)
        {
            this.migrationsAssembly = migrationsAssembly;
        }
    
        protected override void Seed(TContext context)
        {
            base.Seed(context);
    
            // Get migration metadata for migrationAssembly
            var migrationMetadata = GetMigrationMetadata(migrationsAssembly);
    
            // Crate DbContext
            var db = Activator.CreateInstance();
            // Remove newly created record in __MigrationHistory
            db.Database.ExecuteSqlCommand("DELETE FROM __MigrationHistory");
    
            // Get provider manifest token
            var token = GetProviderManifestToken(db);
            // Get sql generator
            var generator = GetMigrationSqlGenerator();
    
            foreach (var migrationMetadatum in migrationMetadata)
            {
                // Create history operation
                var op = CreateInsertHistoryOperation(migrationMetadatum);
                // Generate history insert statements
                var statements = GenerateInsertHistoryStatements(generator, op, token);
                // Run statements (SQL) over database (db)
                RunSqlStatements(statements, db);
            }
        }
    }
    

提交回复
热议问题