Thursday, September 3, 2015

Entity Framework - Specify Different Connection String Programmatically

I was pretty sure that I wasn't the first person to run into this problem - being able to specify a different connectionString entry for use with my entity framework DbContext class.  Most of the time having the one entry just works and all you need to worry about is adjusting the database location, username, password and sometimes the catalog as your application migrates from development, QA, and then (hopefully) into production.

But what happens if you are needing to use your EF DbContext class on to two different data sources in the same application?

Why I had to do this was I needed quickly get the QA environment ready for testing an upgrade by copying the entire content of Production.  This environment refresh included database as well as LDAP content (minus passwords) that needed to be in sync in order for the QA environment to function properly.  

I was left speechless when I realized that my entity framework constructor didn't, initially, allow me to override the name of the entry in the connectString section of the app.config file.  I was even more surprised at the numerous creative ways developers managed to get around this as illustrated by searching StackOverflow.  After reading over several different versions spanning the past few years I became overwhelmed and decided that, after lunch, I'd find another way to do what I wanted to do.  After all I surmised this process was going to be used by a highly technical and detail oriented staff and we could easily run a couple of different processes to get the QA environment refreshed.

But after lunch I had another thought and opened up the model's context class and looked at the constructor.
public SampleEntities()
            : base("name=SampleEntities")
        {
        }

My first thought was, it really couldn't be that easy.  Could it?  "SampleEntities" was the name of the connection string in my app.config file.  On hunch I added another constructor.  This time allowing a different name to be specified in the constructor.
public SampleEntities(string connectionName)
            : base("name=" + connectionName)
        {
        }

Once that hard work was completed I went over and tested it out.
using (SampleEntities entities = new SampleEntities("DestinationDatabase"))
            {
                var customers = entities.Customers.FirstOrDefault();
                Console.WriteLine(customers.EmailAddress);
            }

It worked.  The key here is that the name provided in the constructor must match the name of entry in the connectionStrings section in your app/web.config file.  I was speechless, amused, and extremely happy this worked.