Ok, I've managed to find a solution myself and I'm quite happy with it.
First, I'll lay out the structure of the application.
I do have a DbContext called AppServerSettingsContext which is defined in the source code like this:
/// <summary>
/// Initializes a new instance of the <see cref="AppServerSettingsDataContext"/>.
/// </summary>
public AppServerSettingsDataContext()
: base("AppServerSettingsDataContext")
{ }
This context has 2 different entities (one for a member and one for all the settings for that specific member).
In order for the migration to be able to execute, I need to have a ConnectionString in the applications configuration file, just like the way we used.
Then, I have another context named AppServerDataContext.
This has 2 constructors as showed below:
/// <summary>
/// Initializes a new instance of the <see cref="AppServerDataContext"/>.
/// </summary>
public AppServerDataContext() :
this(ConfigurationManager.ConnectionStrings["AppServer"].ConnectionString)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="AppServerDataContext"/>.
/// </summary>
/// <param name="connectionString">The full connection string which is used to connect to the database.</param>
public AppServerDataContext(string connectionString)
: base(connectionString) { }
You'll see in the code that I can either specify the connection string or I load the connection string for the application configuration file.
You'll see why this is important later on.
I have the DbContext which points to a connection string inside a configuration file. It's not required to have this, but I'm used to work that way. So that connection string will ONLY be used when calling the add-migration command. This is because that command requires a database to check the current state of the database and add the correct migration.
Now, I'm working inside one single project with 2 context files, so the NuGet Package Manager Console needs a way to identify this.
Therefore, the following commands can be used:
Enable migrations for a specific context:
- `PM> Enable-migrations -ContextTypeName: -MigrationsDirectory:
This is a command which I need to execute twice, once for every context.
Then, in the Seed method of my AppServerSettings context, I'll write the following code:
/// <summary>
/// Runs after upgrading to the latest migration to allow seed data to be updated.
/// </summary>
/// <param name="context">Context to be used for updating seed data.</param>
protected override void Seed(AppServerSettingsDataContext context)
{
// Creates the Member and assign all the settings which are required for the application to function.
context.Members.AddOrUpdate(x => x.Name, new Member("Povlo")
{
Settings = new List<MemberSettings>
{
new MemberSettings("DatabaseConnectionString", "Removed for Security Reasons"),
}
});
// Make sure that for every member, the database is created by using the "MigrateDatabaseToLatestVersion" migration.
foreach (var setting in context.Members.Select(member => member.Settings.FirstOrDefault(x => x.Key == "DatabaseConnectionString")))
{
using (var appServerContext = new AppServerDataContext(setting.Value))
{
var de = new MigrateDatabaseToLatestVersion<AppServerDataContext, AppServer.Configuration>();
de.InitializeDatabase(appServerContext);
appServerContext.Database.Initialize(true);
}
}
}
What I do here basically is first creating a member with a given connection string (there can be multiple).
Then, in the same method, I do have a foreach loop, which will create a context based on the connection string in the database. Then for this context, the database is being upgraded to the latest version.
The advantage of this is that I'm using a code-first approach, and all the databases are always the latest version.
A disadvantage of this is that all models needs to be exactely the same.
Database.SetInitializerwith a connection string, not a connection string name.DbContextwithDbConnectionparameter, that you can create as you with, f.e. you can pass the connection string toSqlConnectionconstructor.