Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code-First: Migrate a database known only at runtime

I'm trying to migrate a database that is only known at runtime, which means that I cannot use the Package Manager Console to update the database. Also it's not just one, but many databases, but it is the same schema for all of them :)

I'm using Ninject to generate and inject the connection string on the DbContext object. The context constructor looks just like this:

public class MyEntities : DbContext
{
    public MyEntities(string database) : base(database) { }
    /* Properties code omitted. */
}

The method to instantiate a context follows:

public MyEntities GetDatabase(string databaseName, string connectionString)
{
    SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString);
    builder.InitialCatalog = databaseName;

    MyEntities context = this._kernel.Get<MyEntities>(new ConstructorArgument(
        "database", builder.ConnectionString));

    Database.SetInitializer<MyEntities>(
        new MigrateDatabaseToLatestVersion<MyEntities, MyEntitiesMigrationConfiguration>("MyEntities"));

    return context;
}

When a context is retrieved the method creates a connection string and passes it as parameter to the constructor of MyEntities. Also I specify in the method the type of migration I want (in this case MigrateDatabaseToLatestVersion).

The migration code follows:

public partial class MyAccountInMonth : DbMigration
{
    public override void Up()
    {
        AlterColumn("AccountsInMonths", "MovementDebtMonth", c => c.Long(nullable: false));
        AlterColumn("AccountsInMonths", "MovementCreditMonth", c => c.Long(nullable: false));
        AlterColumn("AccountsInMonths", "BalanceMonth", c => c.Long(nullable: false));
        AlterColumn("AccountsInMonths", "MovementDebtAccumulated", c => c.Long(nullable: false));
        AlterColumn("AccountsInMonths", "MovementCreditAccumulated", c => c.Long(nullable: false));
        AlterColumn("AccountsInMonths", "BalanceAccumulated", c => c.Long(nullable: false));
    }

    public override void Down() { /* Code omitted */ }
}

When I run the application, the following error occurs:

Cannot find the object "AccountsInMonths" because it does not exist or you do not have permissions.

What the migration does is change the type of the column AccountsInMonths from int to long.

It is a migration error, because the stack trace has calls to it. At this moment I can only think that the problem can be permissions because the table exists. Other possibility is some kind of problem on the connection string. Please, anybody has a clue for this? Thanks in advance!

PS: if it is not clear I can add more information to the question.

like image 333
jmpcm Avatar asked Apr 26 '12 13:04

jmpcm


People also ask

How do I code my first migration to an existing database?

Run the Add-Migration InitialCreate command in Package Manager Console. This creates a migration to create the existing schema. Comment out all code in the Up method of the newly created migration. This will allow us to 'apply' the migration to the local database without trying to recreate all the tables etc.

How do you use code first when an existing database schema?

To use code-first for an existing database, right click on your project in Visual Studio -> Add -> New Item.. Select ADO.NET Entity Data Model in the Add New Item dialog box and specify the model name (this will be a context class name) and click on Add.

How do I turn on automatic migration in Entity Framework?

Open the Package Manager Console from Tools → Library Package Manager → Package Manager Console and then run the enable-migrations –EnableAutomaticMigration:$true command (make sure that the default project is the project where your context class is).


2 Answers

I Had the several issue. Here is the solution:

1) Make your Configuration as a public class:

public sealed class Configuration : DbMigrationsConfiguration<YourContextClassHere>

2) Make your Seed() method as a public

2) Add anywhere the code below, this will apply the latest migration and updates your db:

Configuration configuration = new Configuration();
configuration.ContextType = typeof(YourContextClassHere);
var migrator = new DbMigrator(configuration);

// This will update the schema of the DB
migrator.Update();
// This will run Seed() method
configuration.Seed(new YourContextClassHere());
like image 181
Maris Avatar answered Oct 04 '22 14:10

Maris


To migrate a database outside of Visual Studio and the Package Manager Console, use the accompanying migrate.exe tool that is located in the EntityFramework nuget package. It basically let you do the same migration from a command line.

like image 30
Peter Lillevold Avatar answered Oct 04 '22 13:10

Peter Lillevold