Reputation: 2566
I want to execute (code-first) migrations using a connectionString that I have constructed myself.
The entry point is a static function with one parameter, the connectionString.
I have a DbContext class called PocModel with both a default constructor.
public PocModel() : base("PocModel")
{ ...
And a context constructor with a string argument:
public PocModel(string nameOrConnectionString): base(nameOrConnectionString)
{ ...
My goal is to perform migrations on the database that is targeted by the connectionString, not the connectionString that EF "magically" creates via the name only (localhost\sqlexpress - PocModel).
This I have not been able to do.
I have an "outer" function declared like this:
public static void MigrateDatabase(string connectionString)
{ ...
This function I have tried to implement in the flw. ways:
DbMigrator migrator = new DbMigrator(new Migrations.Configuration());
migrator.Configuration.TargetDatabase = new DbConnectionInfo(connectionString, "System.Data.SqlClient");
migrator.Update();
And like this:
Database.DefaultConnectionFactory = new SqlConnectionFactory(connectionString);
Database.SetInitializer<PocModel>(new MigrationInitializer());
PocModel model = new PocModel(connectionString);
model.Dispose();
I have even tried to dynamically set the
ConfigurationManager.ConnectionString["PocModel"]
To the connectionString passed in.
But alas, all fails and the default PocModel constructor is invoked from within the EF migration code, targetting server:localhost\sqlexpress and database:PocModel.
I have not been able to perform migrations to any database not named "PocModel" residing on "localhost\sqlexpress".
It is not an option for me to be using an app.config file to set my connectionString, as I need to pass this in via the static outer function.
Please help, been stuck on this problem for a very long time now.
EDIT: I have made it work by this hack, but I am asking the question in order to verify that there indeed is no other solution to the problem (aka the EF migrations is faulty)
private static string _databaseNameOrConnectionString = "PocModel";
internal static string DatabaseNameOrConnectionString
{
get { return _databaseNameOrConnectionString; }
//HACK: This setter must ONLY be called from SetupModule.MigrateDatabase. It is a hack to circumvent the code-first migrations usage of this ctor.
set { _databaseNameOrConnectionString = value; }
}
//the code first migrations will call this ctor and ignore the connectionString it have been passed.
public PocModel()
: base(DatabaseNameOrConnectionString)
{
Upvotes: 4
Views: 1491
Reputation: 1309
For those who find that their connection string is ignored...
There appears to be a bug in this part of the framework
var configuration = new TMigrationsConfiguration();
configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString,"System.Data.SqlClient");
var migrator = new DbMigrator(configuration);
migrator.Update();
Does not act the same as
var configuration = new TMigrationsConfiguration();
var migrator = new DbMigrator(configuration);
migrator.Configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString,"System.Data.SqlClient");
migrator.Update();
That is - the Target database is ignored if changed after creating the migrator. You must set TargetDatabase before adding to the migrator.
Upvotes: 0
Reputation: 1
I had the same problem as you. However I found a solution that you said that you tried but didn't work. The following code did work for me. I found it here http://romiller.com/2012/02/09/running-scripting-migrations-from-code/
var configuration = new Configuration();
configuration.TargetDatabase = new DbConnectionInfo("Server=MyServer;Database=MyDatabase;Trusted_Connection=True;",
"System.Data.SqlClient");
var migrator = new DbMigrator(configuration);
migrator.Update();
Upvotes: 0
Reputation: 10416
The Update-database call is using the default constructor, so you have to modify that function. You mentioned you have a static class to do this, I couldn't figure out a way to make this work without a static helper.
public static class Helper
{
public static string GetConnectionString()
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = @".\sqlexpress";
builder.InitialCatalog = "migrateme";
builder.IntegratedSecurity = true;
builder.MultipleActiveResultSets = true;
return builder.ConnectionString;
}
}
and then instead of calling the base constructor, I called the constructor with the custom string, and it created the correct database
public PocModel() : base(Helper.GetConnectionString())
{
}
Upvotes: 1