When I create a context with a default connection string (as read from the app.config
) the database is created and the migrations work - basically everything is in order. Whereas when the connection string is created programatically (using SqlConnectionStringBuilder
):
- database isn't created when the database is not present (scenario
A
); CreateDbIfNotExists()
creates the newest version of database model but the migration mechanisms are not invoked (scenarioB
).
In A
an exception is thrown when I wish to access the database, as - obviously - it isn't there. In B
database is created properly migration mechanisms are not called, as is the case in standard connection string.
app.config:
"Data Source=localhost\\SQLEXPRESS;Initial Catalog=Db13;User ID=xxx;Password=xxx
"
builder:
sqlBuilder.DataSource = x.DbHost;
sqlBuilder.InitialCatalog = x.DbName;
sqlBuilder.UserID = x.DbUser;
sqlBuilder.Password = x.DbPassword;
initializer:
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<
MyContext,
Migrations.Configuration
>()
);
Specs: Entity Framework: 5.0, DB: SQL Server Express 2008
For migrations you can either (1) use
MigrateDatabaseToLatestVersion
which will kick in automatically when you start using any of the entities in your context or (2) useDbMigrator
to explicitly tell EF to kick off the migration. The advantage of (2) is that you don't have to perform a dummy operation (likeAddJunk
in @philsoady's example), and you could even useMigratorScriptingDecorator
if you wanted to extract the migration SQL (see Example 2 in the code)The trick with (2) seems to be in ensuring that the same connection string is used consistently by your
DbMigrationsConfiguration
andDbContext
classes. Note that multiple contexts are instantiated during the course ofDbMigration.Update
- all of which call the context's default constructor (so watch out if you have more than one constructor). You also have 2 options here - you can use aconnection string name
in the app.config (but then you can't programmatically define the connection string) or build\hardcode\load etc... a completeconnection string
. See the comments in the code below.Tested in EF 6.0.1 & 6.0.2
If your migration does not work correctly try to set
Database.Initialize(true)
in DbContext ctor.I have similar problem with migrations. And in my solution I have to always set database initializer in ctor, like below
In custom initializer you have to implement
InitalizeDatabase(CustomContex context)
method, eg.UPDATED
He is a solution, with NO Connection strings in app.config. Uses automatic migrations and 2 databases using the same context. The real runtime supplied Connection. Approach.
APP.CONFIG (Uses EF 6)
I rewrote the code to make as small as possible for Demo:
I wanted to automatically migrate when running in DEBUG to make it easy for the devs (the production installer does the migrations normally) but had the same problem, a code-specified connection string is ignored when migrating.
My approach was to derive the migrating contexts from this generic which handles "saving" the connection string:
The ReSharper warning is because static fields in a generic class are only static per concrete type which in our case is exactly what we want.
Contexts are defined as:
which can be used normally.
Look at this link: It gives you more freedom to activate the migrations yourself for each database.
I solved this by using a static connection string to a specific database, inside the default constructor.
Let's say I have several databases, all are based on the same schema: myCatalog1, myCatalog2 etc. I use only the first database connection string in the constructor like this:
This constructor is used only for the
Add-Migration
command to work and create the migrations. Note that there are no side effects for the rest of the databases and if you need another constructor for initializing the context (for other purposes except for migrations), it will work.After I run the
Add-Migration
like this:I can call the next code (taken from the link provided at the beginning) in order to update migrations to each one of my databases which are based on the same schema as myCatalog1:
I've come to similar conclusions.
We had a lengthy discussion on that yesterday. Take a look at it.
If connection is invoked via DbContext ctor - it's where problems appear (simplified). As
DbMigrator
actually calls your 'default empty' constructor - so you get a mix of things. I had some really strange effects from it. My conclusion was that normal initializerCreateDb...
works - but migrations don't (and even fail, throw errors in some cases).