Wednesday, December 11, 2013

Note to self - how to do many to many in Entity Framework code-first

I've probably done a handful of EF code-first projects and I always forget how to do the mappings. I always end up looking at old projects and try to figure out what went on. This is a good place to make notes. In my last project I had no idea what I was looking at. Old age has crept up.

I won't go over the whole DbContext Model classes thing,  but in case someone is reading this that isn't familiar, you make a your model classes for your application and they become mapped to your database entities in the Entity Framework ORM world.

So, for example say we have these two model classes amongst our many other model classes:
  • WatchingList
  • Thing


We would then create our DbContext class by creating a class and implementing from DbContext class. For example:

public class MyProjectDbContext : DbContext
{
   // in here we will map our model objects with DbSet<>
   public DbSet<WatchingList> WatchingLists { get; set;}
   public DbSet<Thing> Things { get; set;}

     ... and so on...
}

The above is where all the magic happens. Look elsewhere for a fuller explanation, but in short when we run our app after having done the above, we can then use LINQ to query the database objects, the database will be created for us if it doesn't already exist.

On another note, if it does already exist then we can configure our project to recreate the database on changes. I'm not going to write about that but it's great do developing though probably not great for production systems :)

Many to Many mapping

Anyway, to do the many to many mappings we'll need a

modelBuilder.Entity<WatchingList>()
      .HasMany((w => w.Things).WithMany()
      .Map(m => m.ToTable("WatchingList_Thing")
      .MapRightKey("ThingId")
      .MapLeftKey("WatchingListId"));

Basically,  ThingId and WatchingListId are the columns in the mapping table and the mapping table will be called  WatchingList_Thing

Abstract base classes

If we have some inheritance with these three model objects say,

  • Animal - maybe an abstract base class for the other two concrete classes listed here
  • Dog - inherits/extends the Animal class
  • Cat - inherits/extends the Animal class
If we have these three model classes declared with DbSet in the usual way we will get three tables with those names. We might want to have the table names in the database slightly different to reflect their relationship. We can do that by also overriding the OnModelCreating() method.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Entity<Animal>().ToTable("Animal");
   modelBuilder.Entity<Dog>().ToTable("Animal_Dog");
   modelBuilder.Entity<Cat>().ToTable("Animal_Cat");
}
So we've controlled the naming of tables by EF.






No comments:

Post a Comment