In an effort to avoid using a table per hierarchy (TPH), I looked at examples of how best to implement table-based inheritance for each class (TPC) in my database model. I came across official documentation and this article .
Below are some class layouts with some simple inheritance.
public class BaseEntity { public BaseEntity() { ModifiedDateTime = DateTime.Now; } [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public DateTime ModifiedDateTime { get; set; } } public class Person : BaseEntity { public string FirstName { get; set; } public string LastName { get; set; } } public class Business : BaseEntity { public string Name { get; set; } public string Location { get; set; } }
DbModelBuilder configurations used in the examples in both articles.
modelBuilder.Entity<BaseEntity>() .Property(c => c.Id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); modelBuilder.Entity<Person>().Map(m => { m.MapInheritedProperties(); m.ToTable("Person"); }); modelBuilder.Entity<Business>().Map(m => { m.MapInheritedProperties(); m.ToTable("Business"); });
The application starts successfully, but when I return to the database, I find three (3) tables instead of the two (2) that I expected to find. After a little testing, the "BaseEntity" table will appear, but it is never used. Everything seems to work just fine, except for an empty blank axis.
I deal with DbModelBuilder configurations, eventually removing the "BaseEntity" configurations that provide the expected result; Two (2) tables, each of which has the correct properties and works correctly.
I do one last test, destroy all DbModelBuilder configurations, include only two properties (2) of DbSet for "Person" and "Business" and test again.
public DbSet<Person> People { get; set; } public DbSet<Business> Businesses { get; set; }
To my surprise, the project is being built, goes to the database, creates only two tables with all the properties of the class, including those inherited from the BaseEntity class. I can do CRUD operations without problems.
After running many tests, I can not find any problems with the final test, and I could not reproduce the duplicate key error, which both articles warned about.
The changes to the database were completed successfully, but an error occurred while updating the context of the object. ObjectContext may be in an inconsistent state. Internal exception message: AcceptChanges cannot continue because the object key values conflict with another object in the ObjectStateManager. Make sure the key values are unique before calling AcceptChanges.
- I'm curious why the examples use the MapInheritedProperties property; is this an obsolete method?
- Why do both examples talk about enabling configuration properties for "BaseEntity", but including either the DbSet property, or any DbModelBuilder configurations for the "BaseEntity" class, force you to create an unused table.
- In relation to the unique key error that the articles warned about; I cannot reproduce the error, and I have tested the primary key many times, both the int generated by the database and the directives generated by the database. Is the information about this error also outdated, or is there a test that I can run to produce the indicated error?