Search code examples
.netentity-frameworkentity-framework-6

Entity Framework 6 set connection string runtime


We are in a mixed environment where our application is using both ADO.NET and Entity Framework.
Since both are pointing to the same physical SQL server, we would like to remove the Entity Framework connection string from the config file and then auto build the string based on the current ADO.NET connection strings.
This saves us from mistakes where a developer changed the ADO.NET string but forgot to change the Entity Framework connection string.

I have read this but they did not answer the question.
How do I create connection string programmatically to MS SQL in Entity Framework 6?

If I create my own DbConnection and pass that to the DbContext(existingConnection, contextOwnsConnection) then it throws an error "The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development."

I am not using Code First.

https://msdn.microsoft.com/en-us/data/jj680699
This talked about code base configuration in EF 6 but the article does not show any code that actually changed the connection string.

UPDATED: More information to help clarify my question.
I am NOT using code first and would like to build a connection string outside of the config file.
The DbContext I am using is a partial class to the auto generated DbContext file that the T4 template is generating.
I was under the impression that I needed to create an inherited DbConfiguration class and do something in that class but the only example I find is using Azure.
https://msdn.microsoft.com/en-us/data/jj680699
There is an article on Code Project that talks about setting the connection string at runtime but the article is based on building a connection string every time I create a new Entity container.
http://www.codeproject.com/Tips/234677/Set-the-connection-string-for-Entity-Framework-at

I would like to be able to use my partial DbContext class to create the connection string so that the caller does not have to do anything special.

UPDATED: Working code for RunTime but not DesignTime
Using code posted by @Circular Reference "listed below", I was able to change the connection string without changing the calls to my Entity class BUT this does not work for DesignTime EDMX file.

public partial class TestEntities : DbContext
{
    public TestEntities() : base(GetSqlConnection(), true)
    {
    }

    public static DbConnection GetSqlConnection()
    {
        // Initialize the EntityConnectionStringBuilder. 
        EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();

        var connectionSettings = ConfigurationManager.ConnectionStrings("Current_ADO_Connection_In_Config");

        // Set the provider name. 
        entityBuilder.Provider = connectionSettings.ProviderName;

        // Set the provider-specific connection string. 
        entityBuilder.ProviderConnectionString = connectionSettings.ConnectionString;

        // Set the Metadata location. 
        entityBuilder.Metadata = "res://*/Models.TestModel.csdl|res://*/Models.TestModel.ssdl|res://*/Models.TestModel.msl";

        return new EntityConnection(entityBuilder.ToString());
    }
}

Now if I can just get the DesignTime working then that would be good.


Solution

  • You are getting the Code First mode exception because you are passing a DbConnection built with the ADO.NET connection string. This connection string does not include references to metadata files, so EntityFramework does not know where to find them.

    To create a DbContext with an appropriate programmatically set connection string, use the EntityConnectionStringBuilder class.

    var entityBuilder = new EntityConnectionStringBuilder();
    
    // use your ADO.NET connection string
    entityBuilder.ProviderConnectionString = conString;
    
    // Set the Metadata location.
    entityBuilder.Metadata = @"res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl";
    var dbContext = new DbContext(entityBuilder.ConnectionString);