Gabriel Llorico
Gabriel Llorico

Reputation: 1803

Entity Framework context.database.create() still goes through my Class : DbMigration

Good day! I would like some ideas on why my context.Database.Create() still goes through my classes : DbMigration. If I dont drop my database, the migration works fine. But if I drop my database and start a new one. It will go through my migration list and try to update and will return an error about dbo."tablename" not found.

Here is the code

    public class DMSDbContextInitializer : DMSDbContextInitializerBase, IDatabaseInitializer<DMSDbContext>
{
    public void InitializeDatabase(DMSDbContext context)
    {
        var dbname = context.Database.Connection.Database;

        if (context.Database.Exists())
        {

            var migrator = new DbMigrator(new MigrationConfiguration
                {
                    AutomaticMigrationsEnabled = false
                });

            //Get all pending migrations
            var pendingmigrations = migrator.GetPendingMigrations().Select(x => new
            {
                numericid = Convert.ToInt64(x.Split(new[] { '_' })[0]),
                migrationid = x
            }).ToList();

            //Get last migration entry
            var latestMigrationHistory = context.GetMigrationHistories().OrderByDescending(x => x.MigrationId).FirstOrDefault();

            if (latestMigrationHistory != null)
            {
                var latestmigrationid = Convert.ToInt64(latestMigrationHistory.MigrationId.Split(new[] { '_' })[0]);

                var prevmigrations = pendingmigrations.Where(x => x.numericid < latestmigrationid);

                //exclude all prev migration in update and insert a fake history table record for each
                foreach (var prevmigration in prevmigrations)
                {
                    context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction,
                        @"INSERT INTO __MigrationHistory (MigrationId,ContextKey,Model, ProductVersion) VALUES (@p0,@p1,@p2,@p3)",
                        prevmigration.migrationid,
                        migrator.Configuration.ContextKey,
                        latestMigrationHistory.Model,
                        latestMigrationHistory.ProductVersion
                        );
                }
            }

            //Execute all valid pending migrations
            if (migrator.GetPendingMigrations().Any())
                migrator.Update();

            /*Some seed and update codes*/
            context.SaveChanges();
        }
        else
        {
            //Create db
            context.Database.Create();
            ConfigureFileTableSupport(context, dbname);
            ConfigureImageFileTableSupport(context, dbname);

            //Initial Data
            Seed(context);
        }

In my context.Database.Create(), if I press F11, it will go through my Class : DbMigration. I cant seem to find what is at fault here.

Here is the DbContext

public class DMSDbContext : BaseDbContext, IDMSDbContext
{
    public DMSDbContext()
        : base("DMSCtx")
    {

    }
    public DMSDbContext(string connectionstring)
        : base(connectionstring)
    {
    }

    public IDbSet<FileMetadata> FileMetadata { get; set; }

    public IDbSet<FileMetadataContent> FileMetadataContents { get; set; }
    public IDbSet<SharedFile> SharedFiles { get; set; }
    public IDbSet<AuditFileMetadata> AuditFileMetadata { get; set; }

    public ITransactionScope CreateTransactionScope()
    {
        return new EfTransactionScope(Database.BeginTransaction());
    }

    public IEnumerable<T> SqlQuery<T>(string sql, params object[] parameters)
    {
        return Database.SqlQuery<T>(sql, parameters);
    }

    public int ExecuteSqlCommand(string sql, params object[] parameters)
    {
        return Database.ExecuteSqlCommand(sql, parameters);
    }

    public string DatabaseName
    {
        get { return Database.Connection.Database; }
    }

    /// <summary>
    /// Query the Migration History Table
    /// </summary>
    /// <returns></returns>
    public IList<MigrationHistory> GetMigrationHistories()
    {
        return Database.SqlQuery<MigrationHistory>("select * from __migrationhistory").ToList();
    }
}

public interface IDMSDbContext
{
    IDbSet<FileMetadata> FileMetadata { get; set; }
    IDbSet<FileMetadataContent> FileMetadataContents { get; set; }
    IDbSet<SharedFile> SharedFiles { get; set; }
    IDbSet<AuditFileMetadata> AuditFileMetadata { get; set; }
    int SaveChanges();
    DbContextConfiguration Configuration { get; }
    ITransactionScope CreateTransactionScope();
    IEnumerable<T> SqlQuery<T>(string sql, params object[] parameters);
    int ExecuteSqlCommand(string sql, params object[] parameters);
    string DatabaseName { get; }
}

Upvotes: 0

Views: 509

Answers (1)

Indregaard
Indregaard

Reputation: 1195

Im not sure why you are implementing the "exact"/close to functionality of how EF migrations works yourself?

Isn't what your after a CreateDatabaseIfNotExists Db initialization strategy? Or is it just me not reading your question good enough?

public class SchoolDBContext: DbContext 
{   
    public SchoolDBContext(): base("SchoolDBConnectionString") 
    {
        Database.SetInitializer<SchoolDBContext>(new CreateDatabaseIfNotExists<SchoolDBContext>());

        //Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseIfModelChanges<SchoolDBContext>());
        //Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseAlways<SchoolDBContext>());
        //Database.SetInitializer<SchoolDBContext>(new SchoolDBInitializer());
    }
    public DbSet<Student> Students { get; set; }
    public DbSet<Standard> Standards { get; set; }
}

Read more: Ef Db initialization strategies More about migrations: Ef Code First Migrations

Upvotes: 2

Related Questions