Entity Framework 4.1: Basics (1)


As I wrote a few days ago, I’ve started to toy around with Entity Framework 4.1, more specifically around the features of Code First.

I’m currently consulting for an SOA project and I have to put forward the solution architecture for many aspect of the solution, including the data access layer.  So I did quite a few POCs in order to make sure the solution I was laying down would hold.

As I mentioned before, the documentation is quite scarce, some related to CTP (1 to 5) with the API slightly different than what it is today.  I’m going to do a series of blog entry around the topics I covered so that you don’t have to search as I had to.

Here’s the first entry where I’ll cover some basics.

As its name suggest, with code-first, you start with the code.  You can create the corresponding database directly from the code, but you could also be working from an existing DB.  The advantage of code-first is that your entity-classes don’t have any EF artefacts on them:  they don’t derive from a specific class and they do not have funky attributes on them.  Well…  for the attributes, as we’ll see, that’s optional!

Let’s start with a simple entity model:  Order and OrderDetail.  We start by modelling it as classes:

public class Order
{
    public int OrderID { get; set; }
    public string OrderTitle { get; set; }
    public string CustomerName { get; set; }
    public DateTime TransactionDate { get; set; }

    public List<OrderDetail> OrderDetails { get; set; }
}

public class OrderDetail
{
    public int OrderDetailID { get; set; }
    public int OrderID { get; set; }
    public decimal Cost { get; set; }
    public string ItemName { get; set; }

    public Order Order { get; set; }
}

Note the following about those classes:

  • They do not derive from any EF classes
  • They do not use EF attributes
  • An Order contains a list of OrderDetail and an OrderDetail contains a reference to its Order
  • Each property is either
    • A simple CLR Type (e.g. string, int, etc.)
    • An entity-type (e.g. Order)
    • A list of entity type (e.g. List<OrderDetail>)

In order to map those class into a DB, we need a container, a database-context:

public class MyDomainContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<OrderDetail> OrderDetails { get; set; }

    static MyDomainContext()
    {
        Database.SetInitializer<MyDomainContext>(new DropCreateDatabaseIfModelChanges<MyDomainContext>());
    }
}

This class is EF-aware.  It doesn’t have to sit in the same assembly than your model classes though.

At least a context must satisfy the following:

  • It derives from System.Data.Entity.DbContext
  • It has a property for each entity set we want to expose
  • Each property is of type System.Data.Entity.DbSet<T> where T is the type of the entity
  • Each property is read / write (get / set)

With that in place, the DbContext base class uses reflection to pick-up the entity-sets and a bunch of convention to infer the underlying database model it should map to.

The conventions take decisions such as for the entity of type Order, the property OrderID must be its primary key.  Other convention will infer the column-name (by default the property name), the column type (e.g. a string maps to nvarchar(128) and should be nvarchar(MAX) in the final version), if a column is nullable (by default, all column but primary and foreign keys are nullable), etc.  .  We’ll see that there are ways to override those conventions.

We’ve added a static constructor here.  The instruction in the static constructor sets a standard for the entire app-domain:  when a database context is initialized, check if the schema in the database is conform to the model and if not drop the DB and recreate it.  The way this is done is that EF creates a table dbo.EdmMetadata and persist a hash of the model schema in it.

If the database doesn’t exist, EF will create it.  Which database?  By default, it creates a DB with the name of your context on the local machine.  You can override that in many ways.  The simplest is to add a connection string in your configuration file with the name of the context (in my case, "MyDomainContext").  Another way is to implement a constructor and call the non-default base-class constructor in it.

In the next blob entry, I’ll show how to override the conventions.

15 thoughts on “Entity Framework 4.1: Basics (1)

  1. Pingback: Entity Framework 4.1: Override conventions (2) « Vincent-Philippe Lauzon's blog

  2. Pingback: Entity Framework 4.1: Deep Fetch vs Lazy Load (3) « Vincent-Philippe Lauzon's blog

  3. Pingback: Entity Framework 4.1: Complex Types (4) « Vincent-Philippe Lauzon's blog

  4. Pingback: Entity Framework 4.1: Many to Many Relationships (5) « Vincent-Philippe Lauzon's blog

  5. Pingback: Entity Framework 4.1: Optimistic Concurrency (6) « Vincent-Philippe Lauzon's blog

  6. Pingback: Entity Framework 4.1: Inheritance (7) « Vincent-Philippe Lauzon's blog

  7. Pingback: Entity Framework 4.1: Bypassing EF query mapping (8) « Vincent-Philippe Lauzon's blog

  8. Pingback: Entity Framework 4.1 Series « Vincent-Philippe Lauzon's blog

  9. Pingback: Entity Framework 4.1 之一 : 基础 » NoName

  10. Cory

    I just wanted to say thank you for taking the time to write this and the other EF 4.1 code first entries. I agree with you 100%…it is hard to find documentation regarding the Code first approach that is not CTP related. I have been struggling for a few days now with seemingly simple scenarios and constantly coming up short. Your articles have been a great help to me while I have worked to try and wrap my head around the “Black Box” called EF. Thanks again and keep up the great work!

    Reply
  11. Nithin

    This is really excellent and extremely helpful. This is what I was looking for but couldn’t find. Keep up the good work.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s