Entity Framework's Code-First with an ObjectContext Entity Framework's Code-First with an ObjectContext

If the following blog interests you, it's probably because you're using Entity Framework with a Code-First approach and whatever it is you are trying to do *must* use an ObjectContext instead of the standard DbContext. I'm sure, like me, you thought this shouldn't be too hard. Then you started hitting roadblocks like, Metadata is required in your connection string. What's metadata? This is only needed in Database-First so you can tell the framework where your edmx and other definition files are, so why do I need this with Code-First, I don't have these files?

This was definitely my first reaction as well. So after much trial-and-error and research, I have the solution!


ObjectContext vs DbContext

To understand how the solution came about, it's important to understand one of the key differences between ObjectContext and DbContext. In the scenario above, it's to do with the metadata. A DbContext is an extension of ObjectContext and is intelligent enough to build its own metadata from either the code or the database. However, ObjectContext is not that smart, it must be strictly supplied the metadata. With Database-First this is easy because the edmx file does this for us. However, with Code-First, it's not.

At first glance this doesn't make sense either, aren't my Code-First models definitions enough? Yes and no. Yes, they are, but not without a few extra lines of code first!

Enough chit-chat, let's get down to the solution. For this example, I have created a new MVC application and added the Entity Framework via the NuGet package manager unless you want to learn how to use SQL Server Convert String to Date with examples.

Next, for cleanliness only, I created a new Domain class library that will house my models and context files.

Inside of this project, I have the following files (also be sure to add the Entity Framework to this project as well):

Creating Code-First Models

Now on to the code, I typically like to create an AppModel for generic properties to share amongst all models:


namespace Domain.Models
{
public class AppModel
{
public long Id { get; set; }
}
}

Next, I created three different models that create a many-to-many relationship, Country, Language, and CountryLanguages.

Country.cs:


namespace Domain.Models
{
public class Country : AppModel
{
public string Name { get; set; }
}
}

Language.cs:


namespace Domain.Models
{
public class Language : AppModel
{
public string Name { get; set; }
}
}

CountryLanguage.cs:


namespace Domain.Models
{
public class CountryLanguage : AppModel
{
public Language Language { get; set; }
public Country Country { get; set; }
}
}

Extending the ObjectContext

Now, I need to create an extension of the ObjectContext which will contain ObjectSet's for the above models. This is contained in the PersistenceContext.cs:


using System;
using System.Collections.Generic;
using System.Data.Entity;
using Domain.Models;
namespace Domain.Persistence
{
public class PersistenceContext : DbContext
{
private readonly Dictionary<Type, object> _dbSets = new Dictionary<Type, object>();
public PersistenceContext(EntityConnection connection) : base(connection)
{
}
private IObjectSet<T> GetDbSet<T>() where T : AppModel
{
if (!_dbSets.ContainsKey(typeof(T)))
{
_dbSets[typeof(T)] = Set<T>();
}
return _dbSets[typeof(T)] as IDbSet<T>;
}
public IObjectSet<Country> Countries {
get { return GetDbSet<Country>(); }
}
public IObjectSet<Language> Languages {
get { return GetDbSet<Language>(); }
}
public IObjectSet<CountryLanguage> CountryLanguages {
get { return GetDbSet<CountryLanguage>(); }
}
}
}

Creating a DbModelBuilder

At this point, I honestly thought I should be able to begin using this objects; however, I was quite wrong. One crucial piecing is still missing. It is contained in the Utils/AppConfig.cs file:


using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using Domain.Models;
namespace Domain.Utils
{
class AppConfig
{
public static DbModelBuilder GetBuilder()
{
DbModelBuilder builder = new DbModelBuilder();
builder.Entity<EdmMetadata>().ToTable("EdmMetadata");
builder.Entity<Language>();
builder.Entity<Country>();
builder.Entity<CountryLanguage>();
return builder;
}
}
}

A new DbModelBuilder must be created that creates the metadata for the ObjectContext to understand how the data is defined. As you can see, I have one builder.Entity<> per model.

The final piece of the puzzle is to actual create a new context and add and query the data. I created a new HomeController.cs in my Controllers folder with the following code:


using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Domain.Models;
using Domain.Persistence;
using Domain.Utils;
namespace MvcApplication2.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public void Index()
{
var connectionString = @"Server=.\SQLEXPRESS;Database=PersistenceContext;Trusted_Connection=true";
DbModelBuilder builder = AppConfig.GetBuilder();
DbConnection connection = new SqlConnection(connectionString);
DbCompiledModel model = builder.Build(connection).Compile();
PersistenceContext context = model.CreateObjectContext<PersistenceContext>(connection);
var temp1 = context.Languages.ToList();
var temp2 = context.Countries.ToList();
var temp3 = context.CountryLanguages.ToList();
context.Dispose();
connection.Dispose();
}
}
}

In the above code the following is done:

  • Create a new connection to a local Sql Express database.
  • Create a new DbModelBuilder that contains the metadata definition of the database.
  • Create a new SqlConnection with the connection string.
  • Create a new DbCompiledModel with the compiled metadata from the builder.
  • Create a new PersistenceContext by calling the CreateObjectContext from the compiled metadata and connection.

That's it, Code-First using an ObjectContext!

The missing LINQ, I mean link, has been found to use ObjectContext and Entity Framework's Code-First approach. The key ingredient is a DbModelBuilder with one Entity<> per model in your application defined. Stay tuned for more Entity Framework fun!

Published on Mar 20, 2019

Tags: Entity Framework Tutorials For Beginners and Professionals | ASP.NET MVC and Web API Tutorial | c#

Related Posts

Did you enjoy this article? If you did here are some more articles that I thought you will enjoy as they are very similar to the article that you just finished reading.

Tutorials

Learn how to code in HTML, CSS, JavaScript, Python, Ruby, PHP, Java, C#, SQL, and more.

No matter the programming language you're looking to learn, I've hopefully compiled an incredible set of tutorials for you to learn; whether you are beginner or an expert, there is something for everyone to learn. Each topic I go in-depth and provide many examples throughout. I can't wait for you to dig in and improve your skillset with any of the tutorials below.