When you derive from DbContext and use the parameter-less constructor it will load a connection string from web.config. You also have the option of explicitly specifying the connectionString using one of the other DbContext constructors.
My particular situation dictates that the connection string CANNOT be specified in the web.config, as the location of the server/username and password are determined at runtime. Easy fix right? Just use the above mentioned constructor to specify the connection string? Wrong.
The problem is that when you specify the connection string using said constructor, it still attempts to use the default provider, so if you're using one or more non standard providers, as I am, it will not work.
I'm sure I can change the default provider in the web.config, but I want to use multiple providers so this will not do.
The only possible way around this that I can see is to use ObjectContext instead of DbContext, which seems to allow you to specify the provider along with the database connection string.
Is there any other way to do it? Is my workaround fairly reasonable?
I believe I can also create a DbContext from an ObjectContext instance.
Create your DbConnection
manually and pass it to the DbContext
constructor as follows:
var conn = DbProviderFactories.GetFactory("MY_CONN_PROVIDER").CreateConnection();
conn.ConnectionString = "MY_CONN_STR";
new DbContext(conn, true);
Notice the second parameter bool contextOwnsConnection
is true
. Since you don't re-use the connection elsewhere, it lets the context manage the connection and Dispose()
it when needed.
You can get to the ObjectContext through IObjectContextAdapter:
((IObjectContextAdapter)context).ObjectContext
DbContext ("context" above) still wraps ObjectContext, so don't worry that you will have a new instance.
You can instantiate DbContext using this overload
public DbContext(ObjectContext objectContext, bool dbContextOwnsObjectContext) {}
for example:
public class YourDbContext : DbContext
{
public YourDbContext() : this(new YourObjectEntities(), dbContextOwnsObjectContext: true)
{}
}
Then you can set your connection string inside of YourObjectEntities:
public partial class YourObjectEntities : ObjectContext
{
public const string ConnectionString = "name=YourEntities"; // Get it from somewhere
public YourObjectEntities() : base(ConnectionString, "YourEntities")
{
// Some initialization, e.g. ContextOptions.LazyLoadingEnabled = false;
}
}
How you specify the provider there is your exercise.