My application has no parameterless constructor at my DbContext
implementation and I don't like to provide a parameterless constructor to a IDbContextFactory<>
implementation.
The reason is I want to keep control where the DbContext points to. That's why all my constructors will ask for the ConnectionStringProvider.
public class MyDbContext : DbContext
{
internal MyDbContext(IConnectionStringProvider provider) : base(provider.ConnectionString) {}
}
and
public class MyContextFactory : IDbContextFactory<MyDbContext>
{
private readonly IConnectionStringProvider _provider;
public MyContextFactory(IConnectionStringProvider provider)
{
_provider = provider;
}
public MyDbContext Create()
{
return new MyDbContext(_provider.ConnectionString);
}
}
I definitely don’t want to add a default constructor! I already did that and it crashed on production because of the wrong connection strings inside the wrong App.config or assuming a default connection string like the default constructor of DbContext
does. I would like use the same infrastructure on
IConnectionStringProvider
)Add-Migration
scriptDbMigrator.GetPendingMigrations()
Currently I get some of those messages:
The context factory type 'Test.MyContextFactory' does not have a public parameterless constructor. Either add a public parameterless constructor, create an IDbContextFactory implementation in the context assembly, or register a context factory using DbConfiguration.
---UPDATE---
This might be a duplicate of How do I inject a connection string into an instance of IDbContextFactory<T>? but it has no solution. I explain why:
Add-Migration
with connection string, so how can I provide a DbContext
or IDbContextFactory<>
that consumes it? Instead of parameterless constructors?
Add-Migration MyMigration -ConnectionStringName "MyConnectionString"
DbMigrator.GetPendingMigrations()
which also asks for parameterless DbContext
or IDbContextFactory<>
implementations.As far as I understand EntityFramework violates encapsulation by implying default constructors and causes temporal coupling which is not fail-safe. So please propose a solution without parameterless constructors.
Create a Migrate Initializer that takes a connection string as constructur parameter then you could pass it to the Migration Constructor so it can use that connection string
public class MigrateInitializer : MigrateDatabaseToLatestVersion<MyContext, Configuration>
{
public MigrateInitializer(string connectionString) : base(true, new Configuration() { TargetDatabase=new System.Data.Entity.Infrastructure.DbConnectionInfo(connectionString,"System.Data.SqlClient") })
{
}
}
The pass it to the MigrateInitializer
public class MyContext : DbContext { public MyContext(string connectionString) : base(connectionString) { Database.SetInitializer(new MigrateInitializer(connectionString)); }
}
Thats it now the migration will use the connection string your provided