我正在尝试使用Code First设置TPC继承。我有一个三级层次结构。 抽象类A,具体类B继承自A,类C继承自B. A类属性:ID,CreatedBy和CreatedOn。 B类属性:FirstName,LastName,BirthDate C类属性:约会日期,状态
我希望在数据库中使用数据库生成的标识创建类B和类C的表。
我的上下文类中有以下代码:
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");
}
我有一个contextinitializer类,它覆盖Seed方法来填充数据库中的一些测试数据。
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();
}
这会在数据库中创建表BClass和CClass,但问题是如果Iam在BClass中插入10行并且在CClass中插入相应的10行,则实体框架在BClass中插入20行,其中10行包含实际值,10行包含Null 。 CClass给出了10行的预期结果。 第二个问题是当我从CClass查询数据时,我没有得到结果。我的错误信息说:
EntitySet'CClass'未在EntityContainer中定义 '的TestContext'。近简单标识符,第1行,第12列。
我正在使用来自http://huyrua.wordpress.com/2011/04/13/entity-framework-4-poco-repository-and-specification-pattern-upgraded-to-ef-4-1/的Huy Nguyen的实体框架4 POCO,存储库和规范模式[升级到EF 4.1]的帖子中的代码,我在通用存储库中的代码看起来像
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));
}
我尝试更改我的表映射但它没有帮助。我不知道我在这里缺少什么,不知道该怎么做。我迫切需要帮助。
提前致谢。
这是我的实际课程的样子:
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; }
}
我的上下文类现在有:
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");
}
答案 0 :(得分:7)
您的映射指定TPT而不是TPC。你必须使用:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<B>().ToTable("BClass");
modelBuilder.Entity<C>().Map(m => m.MapInheritedProperties()).ToTable("CClass");
}
我想要在数据库中创建B类和C类的表 与数据库生成的身份。
EF不会为你做这件事。这将需要对生成的代码进行自定义修改,因为一旦使用继承实体,在整个继承层次结构中的所有实例中必须具有唯一的Id = id在B和C表之间必须是唯一的。这可以通过为种子0指定标识,为B和种子1指定递增2,为C指定递增2,但每次添加新的子实体类型时都必须修改它。
您的存储库非常糟糕。当您使用DbContext时,为什么要转换回ObjectContext?阅读有关使用和查询DbContext的内容,并在没有存储库的情况下启动。 ObjectContext API也不允许在查询中使用派生类型。您必须查询顶级映射实体类型,并使用OfType
扩展方法仅获取派生类型。
var cs = objectContext.CreateSet<B>().OfType<C>().ToList();
另一个通用方法不起作用的例子。
修改强>
对不起,我知道问题出在哪里。我在描述中禁食,我跳过了解决方案的一个重要细节。我没有映射A(EntityBase
),因为它不需要。它被标记为抽象实体,因此不需要为TPC继承中始终为空的单独表。这也是我的B(Person
)在其映射中不调用MapInheritedProperties
的原因,因为我把它作为映射继承的根。因此,为我的示例定义的DbSet必须定义为:
public DbSet<Person> People { get; set; }
如果您想定义DbSet<EntityBase>
,则必须采用与Person
相同的方式映射Employee
:
modelBuilder.Entity<Person>().Map(m => m.MapInheritedProperties()).ToTable("Person");
您当前的映射将EntityBase
和Person
定义为TPT继承的一部分,Employee
作为TPC继承,但EF不喜欢组合继承类型。