I'm trying to set up a TPC inheritance using Code First. I have a three level heirarchy. Abstract class A, concrete class B inherits from A and a class C inherits from B. Class A properties: ID, CreatedBy and CreatedOn. Class B properties: FirstName, LastName, BirthDate Class C properties: Appointmentdate, Status
I want tables for class B and class C to be created in the database with identity generated by the database.
I have following code in my context class:
public DbSet<B> BList { get; set; }
public DbSet<C> CList { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<B>().ToTable("BClass");
modelBuilder.Entity<C>().ToTable("CClass");
}
I have a contextinitializer class which override Seed method to populate some test data in database.
protected override void Seed(TestContext context)
{
TestDataClass testData = new TestDataClass();
List<B> bList= testData.GetBList();
foreach (B objB in bList)
{
context.BList.Add(objB);
}
List<C> cList = testData.GetCList();
foreach (C objC in cList)
{
context.CList.Add(objC);
}
context.SaveChanges();
}
This creates the tables BClass and CClass in the database but the problem is if Iam inserting 10 rows in BClass and corresponding 10 rows in CClass, the entity framework inserts 20 rows in BClass with 10 rows with actual values and 10 rows with Nulls. CClass gives the expected results with 10 rows. The second problem is I don't get the results when i query for the data from CClass. I error message says:
The EntitySet 'CClass' is not defined in the EntityContainer 'TestContext'. Near simple identifier, line 1, column 12.
I am using code from Huy Nguyen's post for Entity Framework 4 POCO, Repository and Specification Pattern [Upgraded to EF 4.1] from http://huyrua.wordpress.com/2011/04/13/entity-framework-4-poco-repository-and-specification-pattern-upgraded-to-ef-4-1/ and my code in generic repository looks like
public IList<TEntity> FindAll<TEntity>() where TEntity : class
{
DbContext.Set<TEntity>();
var entityName = GetEntityName<TEntity>();
return ((IObjectContextAdapter)DbContext).ObjectContext.CreateQuery<TEntity>(entityName).ToList<TEntity>();
}
private string GetEntityName<TEntity>() where TEntity : class
{
DbContext.Set<TEntity>();
return string.Format("{0}.{1}", ((IObjectContextAdapter)DbContext).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}
I tried changing my table mappings but it didn't help. I don't know what am i missing here and not sure what to do. I am in urgent need of help.
Thanks in advance.
This is how my actual classes looks like:
public abstract class EntityBase
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
public virtual long Id { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime? CreatedOn { get; set; }
public virtual string LastModifiedBy { get; set; }
public virtual DateTime? LastModifiedOn { get; set; }
}
public class Person: EntityBase
{
public virtual string FirstName { get; set; }
public virtual string MiddleName { get; set; }
public virtual string LastName { get; set; }
public virtual DateTime? BirthDate { get; set; }
[NotMapped]
public virtual string FullName
{
get
{
return String.Format("{0}, {1} {2}", LastName, FirstName, MiddleName);
}
}
}
public partial class Employee : Person
{
[Required]
public string EmployeeNumber { get; set; }
[Required]
public string department { get; set; }
public DateTime? JoiningDate { get; set; }
public DateTime? PromotionDate { get; set; }
}
and my context class now has:
public DbSet<EntityBase> People { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Person>().ToTable("Person");
modelBuilder.Entity<Employee>().Map(m => m.MapInheritedProperties()).ToTable("Employee");
}