Using DbContext in EF 4.1 Part 2: Connections and Models

 


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.

For Connections and Models see https://msdn.com/data/jj592674


 

Introduction

Version 4.1 of the Entity Framework contains both the Code First approach and the new DbContext API. This API provides a more productive surface for working with the Entity Framework and can be used with the Code First, Database First, and Model First approaches. This is the second post of a twelve part series containing collections of patterns and code fragments showing how features of the new API can be used.

The posts in this series do not contain complete walkthroughs. If you haven’t used EF 4.1 before then you should read Part 1 of this series and also Code First Walkthrough or Model and Database First with DbContext before tackling this post.

Using DbContext constructors

Typically an Entity Framework application uses a class derived from DbContext, as shown in the Code First and Model and Database First with DbContext walkthroughs. This derived class will call one of the constructors on the base DbContext class to control:

  • How the context will connect to a database—i.e. how a connection string is found/used
  • Whether the context will use Code First, Database First, or Model First
  • Additional advanced options

The following fragments show some of the ways the DbContext constructors can be used.

Use Code First with connection by convention

If you have not done any other configuration in your application, then calling the parameterless constructor on DbContext will cause DbContext to run in Code First mode with a database connection created by convention. For example:

 namespace Magic.Unicorn
{
    public class UnicornsContext : DbContext
    {
        public UnicornsContext()
        // C# will call base class parameterless constructor by default
        {
        }
    }
}

In this example DbContext uses the namespace qualified name of your derived context class—Magic.Unicorn.UnicornsContext—as the database name and creates a connection string for this database using SQL Express on your local machine.

Use Code First with connection by convention and specified database name

If you have not done any other configuration in your application, then calling the string constructor on DbContext with the database name you want to use will cause DbContext to run in Code First mode with a database connection created by convention to the database of that name. For example:

 public class UnicornsContext : DbContext
{
    public UnicornsContext()
        : base("UnicornsDatabase")
    {
    }
}

In this example DbContext uses “UnicornsDatabase” as the database name and creates a connection string for this database using SQL Express on your local machine.

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

You may choose to put a connection string in your app.config or web.config file. For example:

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

This is an easy way to tell DbContext to use a database server other than SQL Express—the example above specifies a SQL Server Compact Edition database.

If the name of the connection string matches the name of your context (either with or without namespace qualification) then it will be found by DbContext when the parameterless constructor is used. If the connection string name is different from the name of your context then you can tell DbContext to use this connection in Code First mode by passing the connection string name to the DbContext constructor. For example:

 public class UnicornsContext : DbContext
{
    public UnicornsContext()
        : base("UnicornsCEDatabase")
    {
    }
}

Alternatively, you can use the form “name=<connection string name>” for the string passed to the DbContext constructor. For example:

 public class UnicornsContext : DbContext
{
    public UnicornsContext()
        : base("name=UnicornsCEDatabase")
    {
    }
}

This form makes it explicit that you expect the connection string to be found in your config file. An exception will be thrown if a connection string with the given name is not found.

Database/Model First with connection string in app.config/web.config file

Database or Model First is different from Code First in that your Entity Data Model (EDM) already exists and is not generated from code when the application runs. The EDM typically exists as an EDMX file created by the Entity Designer in Visual Studio. The designer will also add an EF connection string to your app.config or web.config file. This connection string is special in that it contains information about how to find the information in your EDMX file. For example:

<configuration>

<connectionStrings>

<add name="Northwind_Entities"

connectionString="metadata=res://*/Northwind.csdl|

res://*/Northwind.ssdl|

res://*/Northwind.msl;

provider=System.Data.SqlClient;

provider connection string=

&quot;Data Source=.\sqlexpress;

Initial Catalog=Northwind;

Integrated Security=True;

MultipleActiveResultSets=True&quot;"

providerName="System.Data.EntityClient"/>

</connectionStrings>

</configuration>

You can tell DbContext to use this connection by passing the connection string name to the DbContext constructor. For example:

 public class NorthwindContext : DbContext
{
    public NorthwindContext()
        : base("name=Northwind_Entities")
    {
    }
}

DbContext knows to run in Database/Model First mode because the connection string is an EF connection string containing details of the EDM to use.

Other DbContext constructor options

The DbContext class contains other constructors and usage patterns that enable some more advanced scenarios. Some of these are:

  • You can use the DbModelBuilder class to build a Code First model without instantiating a DbContext instance. The result of this is a DbModel object. You can then pass this DbModel object to one of the DbContext constructors when you are ready to create your DbContext instance.
  • You can pass a full connection string to DbContext instead of just the database or connection string name. By default this connection string is used with the System.Data.SqlClient provider; this can be changed by setting a different implementation of IConnectionFactory onto context.Database.DefaultConnectionFactory.
  • You can use an existing DbConnection object by passing it to a DbContext constructor. If the connection object is an instance of EntityConnection, then the model specified in the connection will be used in Database/Model First mode. If the object is an instance of some other type—for example, SqlConnection—then the context will use it for Code First mode.
  • You can pass an existing ObjectContext to a DbContext constructor to create a DbContext wrapping the existing context. This can be used for existing applications that use ObjectContext but which want to take advantage of DbContext in some parts of the application.

Defining sets on a derived context

DbContext with DbSet properties

The common case shown in Code First examples is to have a DbContext with public automatic DbSet properties for the entity types of your model. For example:

 public class UnicornsContext : DbContext
{
    public DbSet<Unicorn> Unicorns { get; set; }
    public DbSet<Princess> Princesses { get; set; }
    public DbSet<LadyInWaiting> LadiesInWaiting { get; set; }
    public DbSet<Castle> Castles { get; set; }
}

When used in Code First mode, this will configure Unicorn, Princess, LadyInWaiting, and Castle as entity types, as well as configuring other types reachable from these. In addition DbContext will automatically call the setter for each of these properties to set an instance of the appropriate DbSet.

DbContext with IDbSet properties

There a situations, such as when creating mocks or fakes, where it is more useful to declare your set properties using an interface. In such cases the IDbSet interface can be used in place of DbSet. For example:

 public class UnicornsContext : DbContext
{
    public IDbSet<Unicorn> Unicorns { get; set; }
    public IDbSet<Princess> Princesses { get; set; }
    public IDbSet<LadyInWaiting> LadiesInWaiting { get; set; }
    public IDbSet<Castle> Castles { get; set; }
}

This context works in exactly the same way as the context that uses the DbSet class for its set properties.

DbContext with read-only set properties

If you do not wish to expose public setters for your DbSet or IDbSet properties you can instead create read-only properties and create the set instances yourself. For example:

 public class UnicornsContext : DbContext
{
    public IDbSet<Unicorn> Unicorns
    {
        get { return Set<Unicorn>(); }
    }

    public IDbSet<Princess> Princesses
    {
        get { return Set<Princess>(); }
    }

    public IDbSet<LadyInWaiting> LadiesInWaiting
    {
        get { return Set<LadyInWaiting>(); }
    }

    public IDbSet<Castle> Castles
    {
        get { return Set<Castle>(); }
    }
}

Note that DbContext caches the instance of DbSet returned from the Set method so that each of these properties will return the same instance every time it is called.

Discovery of entity types for Code First works in the same way here as it does for properties with public getters and setters.

Summary

In this part of the series we showed how to use the various constructors on DbContext to configure connection strings and the Code First, Model First, or Database First mode of the context. We also looked at the different ways that sets can be defined on a derived context.

As always we would love to hear any feedback you have by commenting on this blog post.

For support please use the Entity Framework Forum.

Arthur Vickers

Developer

ADO.NET Entity Framework