5

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.

3 Answers 3

4

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());
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for the suggestion! This problem arose when I was working on a project on my old company. Unfortunately I cannot try this approach you suggest, so I let it open to others who have the same issue!
2

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.

2 Comments

Can I do that with SQL Azure databases?
Haven't tried. Yet. I would expect so since its just a variation on Sql Server.
1

You can use the Package Manager Console with Update-Database. It has a switch to specify connection string - either connection string itself ($ConnectionString and $ConnectionProviderName) or named one from config ($ConnectionStringName).

Or you can use DbMigrator class to handle it yourself in code (similar to what's actually migrate.exe doing).

2 Comments

for now it is a good solution because I'm in development stage. But if it happens in the future it can be unfeasible because there is 1 database for access (hope there are many people accessing). So, for example, for 1000 accesses there will be 1000 databases and your solution is not the best. But it is a good suggestion for now :) Thanks!
@jmpcm I added a note about DbMigrator class to my answer, maybe that might help you to do that in a batch.

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.