DbContext, POCO templates and codefirst-mode

Posted : Sunday, 29 April 2012 09:44:00

I use Entity Framework a lot these days, I’m not saying its perfect but its a come a long way. Its definitely a lot easier to get up and running than NHibernate and this is thanks in no small part to the tooling available from within the Visual Studio IDE. Typically I’ve found my usual “new-application workflow” to consist of the following steps

  1. design a set of entities using the model-first approach
  2. use entities from step 1 to generate a database
  3. add ADO.NET DbContext Generator template to convert the entities to POCO classes
  4. add view layer

While step 3 isn’t totally necessary, without it all the entities will inherit from EntityObject and any part of the application that uses them will need a reference to the entity framework and that just isn’t right!

So when you perform step 3 you get a T4 generated DbContext derived class that will look something like this….

    1 //------------------------------------------------------------------------------

    2 // <auto-generated>

    3 //    This code was generated from a template.

    4 //

    5 //    Manual changes to this file may cause unexpected behavior in your application.

    6 //    Manual changes to this file will be overwritten if the code is regenerated.

    7 // </auto-generated>

    8 //------------------------------------------------------------------------------


   10 using System;

   11 using System.Data.Entity;

   12 using System.Data.Entity.Infrastructure;


   14 namespace CodeFirstMode

   15 {

   16     public partial class CodeFirstModeModelEntities : DbContext

   17     {

   18         public CodeFirstModeModelEntities()

   19             : base("name=CodeFirstModeModelEntities")

   20         {

   21         }


   23         protected override void OnModelCreating(DbModelBuilder modelBuilder)

   24         {

   25             throw new UnintentionalCodeFirstException();

   26         }


   28         //DbSet<Entity1> Entities1

   29         //DbSet<Entity2> Entities2

   30         //....etc

   31     }

   32 }


Notice the UnintentionalCodeFirstException, googling this doesn’t reveal much other than…

“The exception that is thrown when a context is generated from the DbContext templates in Database First or Model First mode, and is then used in Code First mode. “

But what is code-first mode and how can I switch between modes. Up until recently this has been only an idle curiosity but I was working on a project where the model development was mostly complete and so not changing very much. I needed to hook into the OnModelCreating routine with a model that had been generated using the DbContext POCO template. Easy enough right? Wrong, I couldn’t find anything anywhere telling me how to switch to code first mode. My assumption was that once I found this undocumeted switch I could apply it, then alter the T4 template to add the code I wanted into the OnModelCreating function (obviously removing the UnintentionalCodeFirstException).

After a bit of poking around I found the answer, it occurred to me that when using code-first from the outset, generally you add a simple connection string to the config file for your application and go from there whereas if you start from the EntityFramework model item templates, an entity framework connecton string gets added (eg the ones with the path to the CSDL, SSDL & MSL as well as the actual database connection string itself. I changed the connectionString property to a regular connectionstring and providerName from “System.Data.EntityClient” to “System.Data.SqlClient”. I reran the application and Bosch! an UnintentionalCodeFirstException.

So to switch into code-first mode just change the connection string from the entity framework specific flavour to a regular vanilla connection string. If the model is quite complex then the fluent mappings will need to be set up correctly manually, if you get stuck a look in the .edmx file can give some clues.

  • (This will not appear on the site)