entity framework6 – 基类的inheritance和导航属性
我的导航属性和inheritance有问题。
这是我的问题:我有一个基类Person
类和inheritance自Person
User
和Worker
类。 在数据库级别,我使用单表inheritance或每层次表(TPH)inheritance。 所以有一个带有鉴别器列的表。
User
和Worker
需要有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
删除Users
和Workers
关系 – >它会抛出一个例外,说它不知道如何映射User
和Company
实体:
无法确定类型“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();