0

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; }
}

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

sorry, i wasnt able to reply earlier, yes I'm implementing that type of initialization. If you will see the edited question with the format of my dbcontext regarding my question. Also I inherit IDatabaseInitializer<DbContext> on my class Initializer.
im still curious to why, even though I created an if-else regarding if exisiting (as you can see above), and force my "context" to create it. It still goes through the list of my migration.
It does seem strange. Database.Create() will disable the initializer strategy when run. How does your startup/config code look like? Are you running something async? your class : DbMigration is that the one named DMSDbContextInitializer?
actually its not included there, the DMSDbContextInitializer is my IDatabaseInitializer (for your case Database.SetInitializer<SchoolDBContext>). Although I was able to make a work around on it/working solution, Ill mark your answer as an answer for my question. Thank you for the time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.