EF6 Code First: Configuring Unmapped Base Types

Posted on January 29, 2013. Filed under: Visual Studio, Entity Framework | Tags: , , , , |

If your object model contains inheritance, Code First gives you two options for the base type – it can either be mapped or unmapped.

A mapped base type means the inheritance hierarchy is represented in the database using either the TPH, TPT or TPC pattern. An unmapped base type means Code First effectively ignores your base type and acts as if the properties defined in the base type were defined on each derived type.

Note: The code in this post is written using EF6 Alpha 2, if you are using a later release you may need to adjust the code to reflect API changes.

Prior to EF6

Prior to EF6 there was no way to configure an unmapped base type. If you wanted to configure a property defined on an unmapped base type you had to explicitly configure it on every derived type.

For example, in the following model we want all types that inherit from EntityBase to use Key as their primary key and to configure ConcurrencyToken as a Rowversion/Timestamp column.

public class EntityBase
{
  public int Key { get; set; }
  public byte[] ConcurrencyToken { get; set; }
}

public class Blog : EntityBase
{
  public string Name { get; set; }
  public string Url { get; set; }

  public List<Post> Posts { get; set; }
}

public class Post : EntityBase
{
  public string Title { get; set; }
  public string Content { get; set; }

  public int BlogId { get; set; }
  public Blog Blog { get; set; }
}

If we were to configure EntityBase using the fluent API then it would be included in the model and Blog and Post would share a table in the database. The only alternative we are left with is to configure the properties for every type that derives from EntityBase.

public class MyContext : DbContext
{
  public DbSet<Blog> Blogs { get; set; }
  public DbSet<Post> Posts { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<Blog>().HasKey(b => b.Key);
    modelBuilder.Entity<Blog>().Property(b => b.ConcurrencyToken).IsRowVersion();

    modelBuilder.Entity<Post>().HasKey(p => p.Key);
    modelBuilder.Entity<Post>().Property(p => p.ConcurrencyToken).IsRowVersion();
  }
}

This is an annoying violation of the DRY (Don’t Repeat Yourself) principle… fortunately EF6 comes heralding good news.

EF6 to the Rescue

EF6 introduces the Custom Code First Conventions feature – personally it’s my favorite new feature. I can define a convention that performs a set of configuration for every entity that derives from EntityBase in my model.

modelBuilder.Types<EntityBase>().Configure(c =>
  {
    c.HasKey(e => e.Key);
    c.Property(e => e.ConcurrencyToken).IsRowVersion();
  });

I’ve written this convention using ‘lightweight conventions’, this part of the custom conventions feature allows you to build conventions using an API surface that looks and feels similar to the Code First Fluent API. For more information the different types of conventions you can write, check out the walkthrough and feature specification.

About these ads

Make a Comment

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

7 Responses to “EF6 Code First: Configuring Unmapped Base Types”

RSS Feed for RoMiller.com Comments RSS Feed

wow, sweet new feature!! thanks

Hello, I have a question. I need to use two dnfrefeit databases,both of them have dnfrefeit structure. could I use two dnfrefeit dbcontexts?. I have looked for this kind of information but I don’t find anything!

Yes, you can absolutely have multiple DbContext’s in your application.

It looks like this feature has changed since the alpha… I think the new syntax is this:

modelBuilder.Types().Configure(c => c.Property(e => e.ConcurrencyToken).IsRowVersion());

Is this correct?

We did change the Entities method to be called Types (to reduce any confusion caused by the fact you can also configure properties on complex types). I’ve updated the post to use this method.

You’re code is also fine, but it’s not setting the property as the key. I used the lambda block syntax (multiple statements in {}) so that I could perform two lines of configuration.

Quick question on the last example in this post “modelBuilder.Types().Configure()..”. I’m actually trying to apply this on a protected internal byte[] ConcurrencyToken { get; set; }. However an error is raised in the OnModelCreating, stating that ConcurrencyToken is not declared on type Blog… any ideas?

Thanks man this will save me a great deal of time. minutes ago i was trying to write a generic method to mass configure my derived types.
However i still can’t figure out how to configure HasOptional & HasRequired. Any idea ?


Where's The Comment Form?

    About

    Rowan works as a Program Manager for the ADO.NET Entity Framework team at Microsoft. He speaks at technical conferences and blogs at romiller.com. Rowan lives in Seattle, Washington with his wife Athalie. Prior to moving to the US he resided in the small state of Tasmania in Australia. Outside of technology Rowan's passions include snowboarding, mountain biking, horse riding, rock climbing and pretty much anything else that involves being active. The primary focus of his life, however, is to follow Jesus.

    RSS

    Subscribe Via RSS

    • Subscribe with Bloglines
    • Add your feed to Newsburst from CNET News.com
    • Subscribe in Google Reader
    • Add to My Yahoo!
    • Subscribe in NewsGator Online
    • The latest comments to all posts in RSS

    Meta

Liked it here?
Why not try sites on the blogroll...

Follow

Get every new post delivered to your Inbox.

Join 163 other followers

%d bloggers like this: