entity framework 5 - How does Database.SetInitializer actually work? (EF code-first create database and apply migrations using several connection strings) -
i trying write method create database , run migrations on it, given connection string.
i need multiple connections because record audit log in separate database. connection strings out of app.config using code
configurationmanager.connectionstrings["master"].connectionstring;
the code works first connection string defined in app.config not others, leads me think somehow getting connection string app.config in manner don't know.
my code create database if not exist is
private static context mycreatecontext(string connectionstring) { // put connection string factory method can appdomain.currentdomain.setdata("connectionstring", connectionstring ); var factory = new contextfactory(); // know need line - cant see how follows uses database.setinitializer(new migratedatabasetolatestversion<context,datalayer.migrations.configuration>()); var context = factory.create(); context.database.createifnotexists(); return context }
the code in migrations.configuration
public sealed class configuration : dbmigrationsconfiguration<datalayer.context> { public configuration() { automaticmigrationsenabled = false; } }
the context factory code
public class contextfactory : idbcontextfactory<context> { public context create() { var s = (string)appdomain.currentdomain.getdata("connectionstring"); return new context(s); } }
thus setting connection string before creating context.
can going wrong, given connection strings same except database name, , migration code runs 1 connection string, doesnt run others?
i wonder if problem understanding how how database.setinitializer works. guessing reflection or generics. how make call setinitializer tie tie actual context?
i have tried following code migrations not run
private static context mycreatecontext(string connectionstring) { database.setinitializer(new migratedatabasetolatestversion<context, datalayer.migrations.configuration>()); var context = new context(connectionstring); context.database.createifnotexists(); }
update:
i can migrations working if refer connection string using public mycontext() : base("mycontextconnection") - points in config
i able migrations working on using different instances of context, if created contextfactory class , passed connection referencing global. ( see answer related question link )
now wondering why has hard.
i'm not sure problems facing, let me try
the easiest way provide connection - , sure works way...
1) use 'dbcontext' class name
- , define connection in app.config (or web.config). that's easiest, should have connection there matches context class name,
2) if put dbcontext via constructor - consistent , use one. i'd suggest 'read' config connections - , again name 'the same' context class (use connection 'name', not actual string),
3) if none present - ef/cf makes 'default' one - based on provider - and context's class name - isn't want,
you shouldn't customize initializers reason - initializers should agnostic , serve other purpose - setup connection in .config - or directly on
dbcontext
always check 'where data' goes - before doing anything.
for how initializer works - check other post of mine, made thorough example
how create initializer create , migrate mysql database?
notes: (from comments)
connection shouldn't dynamic - config right place be, unless have reason.
constructor should work fine too.
createdbifnotexists
doesn't work 'migration' initializer. can use migratedatabasetolatestversion
initializer. don't 'mix'
or - put public mycontext() : base("mycontextconnection")
- points <connectionstrings>
in config
to point connection - use 'name' , put constructor.
or use somehting configurationmanager.connectionstrings["commentscontext"].connectionstring
regarding entertaining 'multiple databases' migrations (local , remote 1 app) - not related - link - migration not working wish... asp.net entityframework
update: (further discussion here - is adding class inherits violation of solid principles if changes behavior of code?)
it getting interesting here. did manage reproduce problems you're facing actually. here short breakdown on think it's happening:
first, worked 'happily':
database.setinitializer(new createandmigratedatabaseinitializer<mycontext, myproject.migrations.configuration>()); (var flip = false; true; flip = !flip) { using (var db = new mycontext(flip ? "name=mycontext" : "name=othercontext")) { // insert records... db.savechanges(); } }
(i used custom initializer other post, controls migration/creation 'manually')
that worked fine w/o initializer. once switched on, ran curious problems.
i deleted db-s (two, each connection). expected either not work, or create 1 db, in next pass (like did, w/o migrations, 'create' initializer).
what happened, surprise - created both databases on first pass ??
then, being curious person:), put breakpoints on mycontext
ctor, , debugged through migrator/initializer. again empty/no db-s etc.
it created first instance on call within flip
. on first access 'model', invoked initializer. migrator took on (having had no db-s). during migrator.update();
constructs mycontext
(i'm guessing via generic param in configuration) - , calls 'default' empty ctor. had 'other connection/name' default - , creates other db well.
so, think explains you're experiencing. , why had create 'factory' support context creation. seems way. , setting 'appdomain' wide 'connection string' (which did actually) isn't 'overriden' default ctor call.
solution see - need run through factory - , 'flip' connections in there (no need static connection, long factory singleton.
Comments
Post a Comment