Connections and Models Management

Description Article
Table of Contents
Summary

An Entity Framework application uses a class derived from DbContext. This derived class will call one of the constructors on the base DbContext class.

The overloaded constructors of the context allow to connect to a database,i.e. how a connection string is found/used.

Description

Overview

When using the Database First or Model First approaches the Entity Data Model (EDM) already exists and can be specified using an Entity Framework connection stringconnection string name or through an EntityConnection object.

When using Code First approach a connection string name or a “normal” connection string can be used.

How It works

The connection to the database (including the name of the database) can be specified in several ways and is dependent of:

i) The DbContext derived class name;
ii) The DbContext class constructor used on (i);
iii) if a configuration file exists; or
iv) If the database name is used instead of a full connection string.

How The Connection String is Found

If the parameterless DbContext constructor is called from a derived context class, then the name of the derived class is used to find a connection string in the “app.config” or “web.config” configuration file.

If no connection string is found, then the name is passed to the DefaultConnectionFactory registered on the Database class.
The connection factory then uses the context name as the database name in a default connection string.

This default connection string due to defined conventions points to .\SQLEXPRESS on the local machine unless a different DefaultConnectionFactory is registered.

If DbContext constructor is parameterized with database name string then the behavior is the same as the parameterless constructor, but the passed database name is used instead.

If DbContext constructor is parameterized with the string in the form “name=myname”, in which case the name must be found in the configuration file or an exception will be thrown.

If a “normal” database connection string is found then the DbContext will use Code First. If the connection found in the configuration file is a “special” Entity Framework connection string, then the DbContext will use Database/Model First and the model specified in the connection string will be used.

An existing or explicitly created DbConnection can also be used instead of the database/connection name.

If the connection object is an instance of EntityConnection, then the model specified in the connection will be used. If the object is an instance of some other type — for example, SqlConnection — then the context will use it for Code First mode.

 

Default Connection Factory and Provider

Visual Studio 2010 includes SQL Express by default and Visual Studio 2012 includes LocalDb.

During installation, the EntityFramework NuGet package checks which database server is available. The NuGet package will then update the configuration file by setting the default database provider that Code First uses when creating a connection by convention.

If SQL Express is running, it will be used, otherwise LocalDb will be registered as the default instead: no changes are made to the configuration file if it already contains a setting for the default connection factory.

Operations
Use Code First with connection by convention (SQLExpress or DbLocal)

If no configuration in found in the application, then calling the parameterless constructor on DbContext will cause:

  • DbContext to run in Code First mode
  • Database connection created by convention: DbContext uses the namespace qualified name of the derived context class as the database name and creates a connection string for this database

How to do it
namespace Demo.EF
{
    public class BreakAwayContext : DbContext
    {
        public BreakAwayContext()
        // C# will call base class parameterless constructor by default
        {
        }
    }
}

In this example DbContext uses the namespace qualified name of the derived context class - Demo.EF.breakAwayContext - as the database name and creates a connection string for this database.

DbContext uses either SQL Express or LocalDb. If both are installed then SQL Express will be used.

Use Code First with connection by convention and specific database name (SQLExpress or DbLocal)

If no configuration in found in the application, then calling the base constructor on DbContext with a “suggested” database name will cause:

  • DbContext to run in Code First mode
  • Database connection created to the database matching the suggested name

How to do it

 

namespace Demo.EF
{
    public class BreakAwayContext : DbContext
    {
        public BreakAwayContext(): base("BreakawayTestDatabase")
        {
        }
    }
}

In this example DbContext uses the namespace qualified name of the derived context class - Demo.EF.breakAwayContext - as the database name and creates a connection string for this database.

DbContext uses either SQL Express or LocalDb. If both are installed then SQL Express will be used.

Use Code First with connection string explictly configured in app.config/web.config file

The connection string is expected to be found in the application configuration file, otherwise an exception will be thrown if a connection string with the given name is not found.

How to do it

Configuration file:

<configuration>
  <connectionStrings>
    <add name="BreakAwayCompactDatabase"
		providerName="System.Data.SqlServerCe.4.0"
		connectionString="Data Source=BreakWay.sdf"/>
  </connectionStrings>
</configuration>

The example below instantiates the DbContext using a connection string name specified programatically:

public class BreakWayContext : DbContext
{
    public BreakWayContext(): base("name=BreakWayCompactDatabase")
    {
    }
}

The example below instantiates the DbContext using a custom static connection string name:

public class BreakWayContext : DbContext
{
    public BreakWayContext(): base("name=" + Common.ConnectionStringName)
    {
    }
}
Use Code First with pre-instantiated connection (DbConnection)
Remarks

If the connection object is an instance of EntityConnection, then the model specified in the connection will be used rather than calculating a model using Code First.

How to do it
public class BreakWayContext : DbContext
{
    public BreakWayContext(): base(new SqlConnection(Common.ConnectionString), false)
    {
    }
}
Use Code First with connection by convention, specific database name and specific provider

When the EF NuGet package is installed a default connection factory was registered that points to either SQL Express or LocalDb, depending on which was installed.

If a different provider is required and the connection string is not set in the configuration file the default factory must be overrided.

If the provider was not registered by Entity Framework installation it must also be added.

This can be done programatically or through the application configuration file: The first as always priority over the second

How to do it
public class BreakAwayContext : DbContext
{
  public BreakAwayContext(string pDatabaseName): base(pDatabaseName)
  {
  }
}

Changing default connection factory through code (overrides configuration file):

class Program
{
  static void Main(string[] args)
  {
    Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0", @"C:\Users\jseixas\dbs\", "");

    //...

    using (var ctx = new BreakAwayContext("dbtest.sdf"))
    {
      //...
    }
  }
}

Changing default connection factory through the application configuration file:

<entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="System.Data.SqlServerCe.4.0" />
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlServerCe.4.0" type="System.Data.Entity.SqlServerCompact.SqlCeProviderServices, EntityFramework.SqlServerCompact" />
  </providers>
</entityFramework>
Use Database/Model First with connection string in app.config/web.config file

Models created with the EF Designer are different from Code First in that the model already exists and is not generated from code when the application runs: The model exists as an EDMX file in the project.

The designer will add an EF connection string to the “app.config” or “web.config” files. This connection string is special in that it contains information about how to find the information in the EDMX file.

How to do it
<configuration>
  <connectionStrings>
    <add name="BreakAway_Entities"
         connectionString="metadata=res://*/BreakAwayDatabase.csdl|
                                    res://*/BreakAwayDatabase.ssdl|
                                    res://*/BreakAwayDatabase.msl;
                           provider=System.Data.SqlClient;
                           provider connection string=
                               &quot;Data Source=.\sqlexpress;
                                     Initial Catalog=BreakAwayDatabase;
                                     Integrated Security=True;
                                     MultipleActiveResultSets=True&quot;"
         providerName="System.Data.EntityClient"/>
  </connectionStrings>
</configuration>

The EF Designer will also generate code that tells DbContext to use this connection by passing the connection string name to the DbContext constructor:

public class BreakAwayContext: DbContext
{
    public BreakAwayContext()
        : base("name=BreakAway_Entities")
    {
    }
}
Use Code First with connection string explictly configured in app.config/web.config file (generic base class)

This follows a generic base class pattern, that ensures that any context class that derive from it use the appropriate connection.

Remarks

Because the constructor is telling DbContext to look for a connection string in the configuration file, a connection named “BreakWayCompactConnection” must be added to the application configuration file.

How to do it
public class BaseContext<TContext> : DbContext
	where TContext: DbContext
{
    static BaseContext(): base("name=BreakWayCompactConnection")
    {
      Database.SetInitializer<TContext>(null);
    }

    protected BaseContext(); base("name=BreakWay")
    {
    }
}

public class BreakWayContext1 : BaseContext<BreakWayContext1>
{
  //...
}

public class BreakWayContext2 : BaseContext<BreakWayContext2>
{
  //...
}
References

[1] Refer to this article for details on connection string parameters.