Entity frame multi-stage inheritance EF code is preferred

I am trying to use Code First to set up TPC inheritance. I have a three-level hierarchy.
Abstract class A, concrete class B inherits from A, and class C inherits from B. < br>Type A attributes: ID, CreatedBy and CreatedOn.
Type B attributes: FirstName, LastName, BirthDate
Type C attributes: appointment date, status

I want to be in the database Use the ID generated by the database to create tables of class B and class C.

My context class has the following code:

public DbSet BList {get; set; }
public DbSet CList {get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating (modelBuilder);

modelBuilder.Entity().ToTable("BClass");
modelBuilder.Entity().ToTable("CClass");
}

I have a contextinitializer class, which overrides the Seed method to fill in some test data in the database.

protected override void Seed(TestContext context )
{
TestDataClass testData = new TestDataClass();

List bList = testData.GetBList();

foreach (B objB in bList)
{
context.BList.Add(objB);
}

List cList = testData.GetCList();
foreach (C objC in cList)
{
context.CList.Add(objC);
}

context.SaveChanges();
}

This will create the tables BClass and CClass in the database, but the problem is if Iam inserts 10 rows in BClass and inserts the corresponding in CClass 10 rows, then Entity Framework inserts 20 rows in BClass, of which 10 rows have actual values ​​and 10 rows have Null. CClass gives the expected result of 10 rows.
The second problem is when I query data from CClass When I did not get the result. My error message said:

The EntitySet’CClass’ is not defined in the EntityContainer
‘TestContext’. Near simple identifier, line 1, column 12.

I am using the one from http://huyrua.wordpress.com/2011/04/13/entity-framework-4-poco-repository-and -specification-pattern-upgraded-to-ef-4-1/Huy Nguyen’s Entity Framework 4 POCO, Repository and Specification Mode [Upgrade to EF 4.1] The code in the post, I look at the code in the general repository It looks like

public IList FindAll() where TEntity: class
{
DbContext.Set();< br /> var entityName = GetEntityName();
return ((IObjectContextAdapter)DbContext).ObjectCo ntext.CreateQuery(entityName).ToList();
}

private string GetEntityName() where TEntity: class
{
DbContext.Set();
return string.Format("{0}.{1}", ((IObjectContextAdapter)DbContext).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name ));
}

I tried to change my table mapping but it didn’t help. I don’t know what I’m missing here, I don’t know what to do. I desperately need help.

Thanks in advance.

This is how my actual class 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; }

}
< br />
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; }
}

My context class now has:

public DbSet People {get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder) ;

modelBuilder.Ent ity().ToTable("Person");
modelBuilder.Entity().Map(m => m.MapInheritedProperties()).ToTable("Employee");
}

Your mapping specifies TPT instead of TPC. You must use:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity( ).ToTable("BClass");
modelBuilder.Entity().Map(m => m.MapInheritedProperties()).ToTable("CClass");
}

I want tables for class B and class C to be created in the database
with identity generated by the database.

EF will not do this for you This will require custom modifications to the generated code, because once an inherited entity is used, there must be a unique Id in all instances in the entire inheritance hierarchy = id must be unique between the B and C tables. This It can be easily done by specifying the identity for seed 0 and adding 2 to B and seed 1 and adding 2 to C, but it must be modified every time a new fruiting entity type is added.

Your repository Very bad. When you use DbContext, why switch back to ObjectContext? Read about using and querying DbContext and start it without a repository. The ObjectContext API also does not allow the use of derived types in queries. You must query the top-level mapped entity type and use the OfType extension method to get only derived types. < /p>

var cs = objectContext.CreateSet().OfType().ToList();

Another general method does not work Example.

Edit:

Sorry, I know where the problem is. I fasted in the description and I skipped an important detail of the solution. I did not map A (EntityBase) because it is not needed. It is marked as an abstract entity, so it does not need to be a separate table that is always empty in TPC inheritance. This is also the reason why my B (Person) does not call MapInheritedProperties in its mapping, because I Take it as the root of mapping inheritance. Therefore, the DbSet defined for my example must be defined as:

public DbSet People {get; set; }

If you want to define DbSet, you must map Person in the same way as Employee:

modelBuilder.Entity().Map(m => m.MapInheritedProperties()).ToTable("Person");

Your current mapping defines EntityBase and Person as part of TPT inheritance, and Employee as TPC inheritance, but EF does not like combined inheritance types. /p>

I am trying to use Code First to set up TPC inheritance. I have a three-level hierarchy.
Abstract class A, concrete class B inherits from A, and class C inherits from B.
Type A attributes: ID, CreatedBy and CreatedOn.
Type B attributes: FirstName, LastName, BirthDate
Type C attributes: appointment date, status

I hope Use the ID generated by the database to create tables of class B and class C in the database.

I have the following code in my context class:

public DbSet< B> BList {get; set; }
public DbSet CList {get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
< br /> modelBuilder.Entity().ToTable("BClass");
modelBuilder.Entity().ToTable("CClass");
}

I have a contextinitializer class which overrides the Seed method to populate some test data in the database.

protected override void Seed(TestContext context)
{
TestDataClass testData = new TestDataClass();

List bList = testData.GetBList();

foreach (B objB in bList)
{< br /> context.BList.Add(objB);
}

List cList = testData.GetCList();
foreach (C objC in cList)
{
context.CList.Add(objC);
}

context.SaveChanges();
}

This will be The tables BClass and CClass are created in the database, but the problem is that if Iam inserts 10 rows in BClass and inserts the corresponding 10 rows in CClass, Entity Framework inserts 20 rows in BClass, of which 10 rows have actual values, 1 Row 0 has Null. CClass gives the expected result of row 10.
The second problem is when I query data from CClass, I don’t get the result. My error message says:

< /p>

The EntitySet’CClass’ is not defined in the EntityContainer
‘TestContext’. Near simple identifier, line 1, column 12.

I am Use Huy Nguyen’s Entity Framework from http://huyrua.wordpress.com/2011/04/13/entity-framework-4-poco-repository-and-specification-pattern-upgraded-to-ef-4-1/ 4 The code in the post of POCO, Repository and Canonical Mode [Upgrade to EF 4.1], my code in the general repository looks like

public IList FindAll() where TEntity: class
{
DbContext.Set();
var entityName = GetEntityName();
return ((IObjectContextAdapter )DbContext).ObjectContext.CreateQuery(entityName).ToList();
}

private string GetEntityName() where TEntity: class
{
DbContext.Set();
return string.Format("{0}.{1}", ((IObjectContextAdapter)DbContext).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}

I tried to change my table mapping but it didn’t help. I don’t know what I’m missing here, don’t know what to do Do. I desperately need help.

Thanks in advance.

This is how my actual class 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]< br /> 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; }< br />
public DateTime? JoiningDate {get; set; }
public DateTime? PromotionDate {get; set; }
}

My context class now has:

public DbSet People {get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity().ToTable("Person");
modelBuilder.Entity().Map(m => m.MapInheritedProperties()).ToTable("Employee");
}

Your mapping specifies TPT instead of TPC. You must use:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder) ;

modelBuilder.Entity().ToTable("BClass");
modelBuilder.Entity().Map(m => m.MapInheritedProperties()). ToTable("CClass");
}

I want tables for class B and class C to be created in the database
with identity generated by the database.

EF will not do this for you. This will require custom modifications to the generated code, because once inherited entities are used, there must be unique among all instances in the entire inheritance hierarchy Id = id must be unique between the B and C tables. This can be easily done by specifying the ID for seed 0 and adding 2 to B and seed 1 and adding 2 to C, but every time a new fruiting entity type is added You have to modify it.

Your repository is terrible. When you use DbContext, why switch back to ObjectContext? Read about using and querying DbContext and start it without a repository. The ObjectContext API also does not allow the use of derived types in queries. You must query the top-level mapped entity type and use the OfType extension method to get only derived types. < /p>

var cs = objectContext.CreateSet().OfType().ToList();

Another general method does not work Example.

Edit:

Sorry, I know where the problem is. I fasted in the description and I skipped an important detail of the solution. I did not map A (EntityBase) because it is not needed. It is marked as an abstract entity, so it does not need to be a separate table that is always empty in TPC inheritance. This is also the reason why my B (Person) does not call MapInheritedProperties in its mapping, because I Take it as the root of mapping inheritance. Therefore, the DbSet defined for my example must be defined as:

public DbSet People {get; set; }

If you want to define DbSet, you must map Person in the same way as Employee:

modelBuilder.Entity().Map(m => m.MapInheritedProperties()).ToTable("Person");

Your current mapping defines EntityBase and Person as part of TPT inheritance, and Employee as TPC inheritance, but EF does not like combined inheritance types. /p>

Leave a Comment

Your email address will not be published.