entity framework6 – 基类的inheritance和导航属性

我的导航属性和inheritance有问题。

这是我的问题:我有一个基类Person类和inheritance自Person UserWorker类。 在数据库级别,我使用单表inheritance或每层次表(TPH)inheritance。 所以有一个带有鉴别器列的表。

UserWorker需要有Company关系,所以我想在Person类上定义它。

我这样定义我的模型:

 [Table("mydb.person")] public abstract partial class Person { [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long ID { get; set; } public long? CompanyID { get; set; } [ForeignKey("CompanyID")] public virtual Company Company { get; set; } ... } public partial class User : Person { ... } public partial class Worker : Person { .... } [Table("mydb.company")] public partial class Company { public Company() { this.People = new HashSet(); this.Users = new HashSet(); this.Workers = new HashSet(); } [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long ID { get; set; } public virtual ICollection People { get; set; } public virtual ICollection Users { get; set; } public virtual ICollection Workers { get; set; } ... } 

现在,当我尝试进行查询以获取用户和相关公司时,例如:

 dbSet.Where(u => u.Username == username).Include(x => x.Company).FirstOrDefault(); 

查询失败,出现此exception:

‘字段列表中的未知列’Extent1.Company_ID’

如果我检查结果SQL它看起来像这样:

 SELECT 1 AS `C1`, @gp2 AS `C2`, `Extent1`.`ID`, `Extent1`.`CompanyID`, `Extent1`.`Username`, ... `Extent1`.`Company_ID` FROM `person` AS `Extent1` WHERE `Extent1`.`Discriminator` = @gp1 

它包含额外的Company_ID列,该列不存在。

我试了几件事,没有成功:

  • 将列从CompanyID重命名为Company_ID – >它在SQL中生成Column_ID1并抛出相同的exception
  • Company删除UsersWorkers关系 – >它会抛出一个例外,说它不知道如何映射UserCompany实体:

无法确定类型“Models.User”和“Models.Company”之间关联的主要结尾。 必须使用关系流畅API或数据注释显式配置此关联的主要结尾。

  • 如果我从Company删除所有3个导航属性,它将抛出与上面相同的映射exception

我现在没有“干净”的想法。 唯一可行的方法是做一些脏黑客,定义子类的所有关系,并在需要用户和工作者的情况下在基类中进行单独的查询和合并。

你有什么建议吗?

删除Users and Workers集合属性。

 public virtual ICollection Users { get; set; } public virtual ICollection Workers { get; set; } 

由于您的公司导航属性是在Person上定义的,因此关联的后退导航属性必须是ICollection of Person。

People集合将包含所有关联的工作者和用户。 这两个额外的属性Users和Workers被解释为全新的关系,并且因为您没有相应的属性,而User或Worker EF上的外键实际上会生成它。

回答评论。 只是为了格式化作为第二个答案;-)

如果您从公司开始,请急切加载

 var companies = db.Company.Include(p => p.People); 

它将永远得到用户和工人。

如果你从人们那里开始使用渴望加载。

 var users = db.People.OfType().Include(p => p.Company).ToList(); var companies = users.Select(p => p.Company).Distinct().ToList(); 

贵公司的People导航属性只有用户。

您还可以执行两个单独的语句,数据库上下文的修复将自动填充导航属性。

 var company = db.Company.Where(p => p.ID > 100).ToList(); var copanyUsers = db.Company.Where(p => p.ID > 100) .SelectMany(p => p.People).OfType().ToList();