抽象类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查询数据时,我没有得到结果.我的错误信息说:
The EntitySet ‘CClass’ is not defined in the EntityContainer
‘TestContext’. Near simple identifier, line 1, column 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"); }您的映射指定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"); }
I want tables for class B and class C to be created in the database
with identity generated by the database.
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>您必须以与Employee相同的方式映射Person:
modelBuilder.Entity<Person>().Map(m => m.MapInheritedProperties()).ToTable("Person");
您当前的映射将EntityBase和Person定义为TPT继承的一部分,Employee作为TPC继承,但EF不喜欢组合继承类型.