I struggled to enable my code to run code first EF migrations using different connection strings, and finally got it working.
The method I used is outlined in my answer to this question
What bothers me is that in order to be able to run the same code using different connection strings I had to
1) Resort to a global setting to store the connection string
2) Introduce a class whose very presence caused the code to behave differently.
This is so different to the way I am used to working. Is the technique used here violating the solid principles? Is there any other way of doing it that does not violate the principles?
UPDATE:
A different approach - possibly more sensible is outlined here
(all this is is related to what's in here
How does Database.SetInitializer actually work? (EF code-first create database and apply migrations using several connection strings) - but was getting into entirely different direction - so I think it makes sense to be separated. Read there before this)
Update:
It is getting interesting here. I did manage to reproduce the problems you're facing actually. Here is a short breakdown on what I think it's happening:
First, this worked 'happily':
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<MyContext, MyProject.Migrations.Configuration>());
for (var flip = false; true; flip = !flip)
{
using (var db = new MyContext(flip ? "Name=MyContext" : "Name=OtherContext"))
{
// insert some records...
db.SaveChanges();
}
}
(I used custom initializer from my other post, which controls migration/creation process together)
That worked fine w/o an Initializer. Once I switched that on, I ran into some curious problems.
I deleted Db-s (two, for each connection). I expected to either not work, or create one db, then another in the next pass (like it did, w/o migrations, just 'Create' initializer).
What happened, to my surprise - is it actually created both databases on the first
pass ??
Then, being a curious person:), I put breakpoints on the MyContext
ctor, and debugged through the migrator/initializer. Again empty/no db-s etc.
It created first instance on my call within the flip
. Then on the first access to 'model', it invoked the initializer. Migrator took over (having had no db-s). During the migrator.Update();
it actually constructs the MyContext
(I'm guessing via generic param in Configuration) - and calls the 'default' empty ctor. That had the 'other connection/name' by default - and creates the other Db all as well.
So, I think this explains what you're experiencing. And why you had to create the 'Factory' to support the Context creation. That seems to be the only way. And setting some 'AppDomain' wide 'connection string' (which you did discover well actually) which isn't 'overriden' by an empty ctor call.
Solution that I see is - you just need to run everything through factory - and 'flip' connections in there (no need for static connection, as long as your factory is a singleton.
This actually doesn't work at all (my test at least) with an official
MigrateDatabaseToLatestVersion
initializer - and the reason why I
used the other one.