What I’m loving about the newest iteration of EF Code First in CTP4

There have been a lot of improvements to code first since CTP3 and in fact, the team has been experimenting with changes to the core Entity Framework APIs that not only support even simpler programming with code first but that we’ll benefit from in an upcoming release of .NET. (No, I don’t know if there will be a service pack and when…)

I have a code first sample in my book, Programming Entity Framework 2nd Edition, that is coming out in August and was lucky with the timing of the CTP4 release because I was able to sneak in an overhaul of that section before the book heads to the printer.

In revising my code sample for that section I was very happy with so many of the API & Code First improvements.

**But first a clarification is important. The version of Entity Framework that is in .NET 4/VS2010 is the current shipping, supported version that you can use in production. What’s in the CTP is simply an early look at what’s coming as it evolves giving us a chance to play with it. This is not something you can deploy and it is also going to evolve with future CTP versions.**

So with that in mind, I went to town on the CTP3 sample.

The first thing that I benefited from was the new stripped down easy access versions of the ObjectContext and ObjectSet.

The new classes, DbContext and DbSet have the same essential functions but don’t expose you to the entire feature set of their big brother & sister. Not everyone needs all of those features. The are not derived from ObjectContext and ObjectSet however, but provide easy access to the full featured versions through a property e.g., DbContext.ObjectContext and DbSet.ObjectSet.

Along with this simplification are simplified terms.

Where ObjectSet has AddObject

context.Customers.AddObject(myCust) – note that Customers in this case is the ObjectSet)

DbSet simply uses Add

context.Customers.Add(MyCust) –>now I’m using Customers as a DbSet).

Another nice trick is how DbSets are created.

ObjectSet has an internal constructor and does not have a parameterless constructor,so you need a backing variable

ObjectSet<Customer> Customers;

and then you need to execute the CreateObjectSet method to create the ObjectSet:

context.CreateObjectSet<Customer>(“Customers”)

DbSet has a constructor so you can use an auto-implemented property

public DbSet<Customer> Customers { get; set; }

Code First gets way easier

It’s true. I cut out gobs of code and moved code to where it belongs.

Code first uses convention over configuration. It looks at your classes and does its best job of inferring a model and a database schema from it (if you are starting from scratch). Your classes don’t always provide enough metadata so you can provide more info to code first through additional configurations. Initially those configurations were programmatic only but now you can also use attributes in your classes (“data annotations”).

Here are two examples.

In my model I have a class called ConferenceTrack. It has an identity property called TrackId. Code first convention looks for “Id” or class name + “Id” as an identity but TrackId doesn’t fit this pattern so I have to tell EF that this is my identity key.

I can do that using code first’s ModelBuilder (formerly called ContextBuilder):

modelBuilder.Entity<ConferenceTrack>().HasKey(ct => ct.TrackId);

In CTP3, I had to execute from the same code that instantiates the context. Bad bad. Now there is an OnModelCreating method that I can use and put that configuration inside that method. The method lives in the context class. I don’t have to call it. The context is smart enough to run it for me.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<ConferenceTrack>().HasKey(ct => ct.TrackId);
}

Alternatively, I can configure this key right in my class as an attribute of the TrackId property.

    [Key]
    public int TrackId { get; set; }

Definitely simpler. I prefer to keep all of that EF related stuff in the context class so will most likely continue to use the fluent configuration rather than the data annotations.

Boy oh Boy did Relationships Get Easier

In my domain classes, I have a bunch of relationships defined through properties.

E.g.

ConferenceTrack has

public ICollection<Session> Sessions  { get; set; }   (a one-to-many relationship)

Session has

  public ConferenceTrack ConferenceTrack { get; set; }  (a many to one relationship)
  public ICollection<Speaker> Speakers { get; set; } (a many to many relationship)

In CTP3 I had a whole bunch of configurations defined (that were hard to construct and hard to read) so that the model would understand my intent with these relationships. CTP4 is now smart enough to grok my intent based on the domain class properties. And if there’s something that I want that doesn’t follow the convention, then I can add a configuration.

So I removed *all* of the configuration code that described the relationships.

That made me happy.

And EF/Code First figured it all out.

Based on my classes and the single configuration to define the TrackId as the key for conferences, it created this database to persist my data into

ctp4

It worked out all of the relationships. Notice the Sessions_Speakers that it created for the many to many relationship.

Also, I have a class in my domain that is called Workshop and inherits from Session. By default Code First assumes Table Per Hierarchy. It created a discriminator column in the Sessions table which I need to use another configuration for to change its name to IsWorkshop.

There's more to love about this CTP. You can get coding details from theEntity Framework Design and EF team blog's newest posts and download the CTP here.

 As I’m learning more about domain driven development and as code first evolves, I’m getting more excited about this upcoming feature of Entity Framework

#1 a avrashow on 7.16.2010 at 6:59 PM

noticed you did a video on pluralsight on POCOs for EF a few days ago. Did this video demo the new features in CTP4?

#2 Julie on 7.16.2010 at 7:37 PM

no. I did that video last week. CTP4 just came out 2 days ago :) But am thinking about it. Not sure if P/S does future tech vids tho.

#3 Sharad on 8.04.2010 at 5:52 AM

What is the difference in ConfTrack relationship and many-many relationship. They look defined similarly - how does it work? I tried, it didn't create the table for me!

I wonder, what did I miss!

Thanks in advance.

#4 Julie on 8.04.2010 at 12:46 PM

@Sharad

Session class has a property for conference track that is a single item.

ConfTrack has a property that is a collection of sessions. So the classes tehmselves define a one to many rel between conftrack and session.

Now to the *:*.

Session has a property that is a collection of speakers.

Speaker has a proeryt that is a collection of sessions

That defines a many to many and EF created a join table to represent that in the db.

hth

julie

Leave a Comment