What is best configuration in CTP 5 for Inheritance?

Hello,

Would like some opinion on what is best to use in CTP 5 for inheritence. Ive heard of 3 ways of doing it. (This is indirectly addressed to Serenarules :D)

Table per Hierarchy ?
Table per Type ?
or able per Concrete Type ?

For those who wondering what the hell is that… refer to http://weblogs.asp.net/manavi/default.aspx which is a nice blog about inheritence and polymorphism in CTP 5. Enjoy!

Thanks.

The ‘best’ is very subjective. It really depends on your entities. You can mix and match depending on your needs. My suggestion is this. Design your domain first, and worry about mapping when your objects actually work together (and all your tests pass).

Once you get that down, you can map as needed. Here are some of the sample from the msdn blog:

TPH:

modelBuilder.Entity<Product>() 
.Map<Product>(m => m.Requires("Type").HasValue("Current")) 
.Map<DiscontinuedProduct>(m => m.Requires("Type").HasValue("Old")); 

TPT:

modelBuilder.Entity<Product>().ToTable("Products"); 
modelBuilder.Entity<DiscontinuedProduct>().ToTable("OldProducts");

TPC:

modelBuilder.Entity<Product>().ToTable("Products"); 
modelBuilder.Entity<DiscontinuedProduct>() 
.Map(m => 
{ 
m.MapInheritedProperties(); 
m.ToTable("OldProducts"); 
});

and here’s one for complex types (ValueObjects like Address):

modelBuilder.ComplexType<Address>();

Model first, then map.

Thanks for your examples.

Well the domain is rather straighforward. I am doing a sample example of MVC 3 working with CTP 5 at the momment. Its like Journal contains JournalEntries which each entries contains tasks, problems and note. Root is journal and there is no validation to be enforced anywhere. (So i guess unit tests aren’t really needed in that case)

There is one thing that make me wonder… in an one-to-many relationship there much be an entity reference on the other side. Why ? lets me explain

public class Journal
{
     public virtual ICollection<JournalEntry> JournalEntries { get; set; }
}
public class JournalEntry
{
     public virtual Journal Journal { get; set; } <<-- [B]why this is needed ? and what its use ?[/B]
}

I am using this mapping :

modelBuilder.Entity<Journal>()
                .HasMany(j => j.Entrees)
                .WithRequired(ej => ej.Journal)
                .HasForeignKey(ej => ej.Id);

It is a working reference to journal ? If so, it is permitted to use a reference to the aggregate root in other aggregate objects ? If that not clear lemme me know :slight_smile:

One more thing to add actually.

Considering the examples above, ask yourself question like, “how often will these discontinued products be accessed”, and, “how many discontinued products do I actually have?”

If you have a lot of records, and the old one won’t be accessed much, you might consider TPT or TPC because the less records there are in a table, the faster full table scans will be. There are also a limited number of auto inc integers before you run out.

If you’re dealing with a small database and just want to minimize maintenance, TPH ought to suffice.

Okay.

The reference to journal is not, in fact, required. Let me give you a small sample:

namespace EFT.Models
{
    public class Category
    {
        public virtual int Id { get; set; }
        public virtual string Title { get; set; }
        public virtual ICollection<Post> Posts { get; set; }
    }
    public class Post
    {
        public virtual int Id { get; set; }
        public virtual string Message { get; set; }
    }
    public class CategoryMap : EntityTypeConfiguration<Category>
    {
        public CategoryMap()
        {
            ToTable("Categories");
            HasKey(x => x.Id);
            Property(x => x.Title)
                .HasColumnType("varchar")
                .HasMaxLength(256)
                .IsRequired();
            HasMany(x => x.Posts);
        }
    }
    public class PostMap : EntityTypeConfiguration<Post>
    {
        public PostMap()
        {
            ToTable("Posts");
            HasKey(x => x.Id);
            Property(x => x.Message)
                .HasColumnType("text")
                .IsRequired();
        }
    }
    public class DomainContext : DbContext
    {
        public DbSet<Category> Categories { get; set; }
        public DbSet<Post> Posts { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
            modelBuilder.Configurations.Add(new PostMap());
            base.OnModelCreating(modelBuilder);
        }
    }
}

With the following connection string in web.config, will auto-generate the database for you. Your Posts table will have a CategoryId foreign key in it.

  <connectionStrings>
    <add
      name="DomainContext"
      providerName="System.Data.SqlClient"
      connectionString="Server=.\\SQLEXPRESS;Database=efctp;Trusted_Connection=true;"/>
  </connectionStrings>

The folks at MS just seem to like back references for some reason. =/

I see. Well that not a bad thing i guess. I may in some scenario need to know which Journal belong to a JournalEntry and vise-versa. Btw… i like how you structured your mapping, i didn’t know we could use classes. :slight_smile: I am learning new stuff everyday lol

Anyway i think that doesnt break any rules. Stuff inside an aggregate root can hold a reference to the aggregate root.

Thanks!