实体框架中的问题建模关系首先使用代码

Posted

技术标签:

【中文标题】实体框架中的问题建模关系首先使用代码【英文标题】:Problem modelling relationship in Entity Framework using code first 【发布时间】:2011-06-12 12:43:49 【问题描述】:

我正在尝试首先在实体框架中学习代码,但在建模关系时遇到了麻烦。这是一个基本的人力资源数据库,为此有两个实体,员工和部门。

员工属于一个部门,该部门有一个团队管理员和一个经理,这两个人实际上都是员工。我尝试使用以下方法对此进行建模:

EMPLOYEE

public int? DepartmentID  get; set; 
public virtual Department Department  get; set; 

Context:

modelBuilder.Entity<Employee>().HasOptional(x => x.Department);

DEPARTMENT

public class Department

    [Required]
    public int DepartmentID  get; set; 

    [Required(ErrorMessage = "The description is required.")]
    public string Description  get; set; 

    public int? ManagerID  get; set; 
    public virtual Employee Manager  get; set; 

    public int? TeamAdministratorID  get; set; 
    public virtual Employee TeamAdministrator  get; set; 


Context:

modelBuilder.Entity<Department>().HasOptional(x => x.Manager);
modelBuilder.Entity<Department>().HasOptional(x => x.TeamAdministrator);

显然,我希望 Department 表只有四列 - DepartmentID、Description、ManagerID 和 TeamAdministratorID,但它会为关系生成额外的两列,即 Manager_EmployeeID 和 Team_Administrator_EmployeeID。此外,在 Employee 表中,生成列 Department_DepartmentID 来存储 DepartmentID,而不是使用我在实体中指定的 DepartmentID 列。

我做错了什么?如何定义字段和关系以避免代码首先忽略我指定的内容并在数据库中生成它自己的导航字段?

【问题讨论】:

【参考方案1】:

那是因为您的模型配置不完整 - 您使用 Fluent API 开始了自己的映射,因此您必须告诉 EF 这些属性确实是关系的 FK。供员工使用:

modelBuilder.Entity<Employee>()
            .HasOptional(x => x.Department)
            .WithMany()
            .HasForeignKey(x => x.DepartmentID);

供部门使用:

modelBuilder.Entity<Department>()
            .HasOptional(x => x.Manager)
            .WithMany()
            .HasForeignKey(x => x.ManagerID);
modelBuilder.Entity<Department>()
            .HasOptional(x => x.TeamAdministrator);
            .WithMany()
            .HasForeignKey(x => x.TeamAdministratorID);

顺便说一句。如果在关系的另一侧没有集合导航属性,将很难使用模型(所有WithMany 都是空的)。至少Department 应该有:

public virtual ICollection<Employee> Employees  get; set;

并且映射应该修改为:

modelBuilder.Entity<Employee>()
            .HasOptional(x => x.Department)
            .WithMany(y => y.Employees)
            .HasForeignKey(x => x.DepartmentID);

【讨论】:

现在我看到它是这样写的,这对我来说更有意义。非常感谢,现在一切正常。 另外,如果你想避免在你的模型中有外键属性,你可以使用 .Map(x => x.MapKey("ForeignKeyColumnName")) 而不是 .HasForeignKey(x => x .ForeignKeyPropertyName)【参考方案2】:

查看您的员工类别

EMPLOYEE    
public int? DepartmentID  get; set; 
public virtual Department Department  get; set; 

为了显示员工和部门之间的关系,您使用了 ID 部门。实际上,您只需执行一次 - 通过Department。默认情况下,EF 搜索 ID 属性并为您链接两个类。所以你的类应该只包含一个 ID - 类本身的 ID。尝试删除其他类的 ID。

【讨论】:

以上是关于实体框架中的问题建模关系首先使用代码的主要内容,如果未能解决你的问题,请参考以下文章

实体框架中的多对多关系导致无限循环

首先使用实体​​框架代码保存单个实体对象

使用对象角色建模 (ORM) 的关系模型中的动态类型

理解实体框架核心外键关系

实体框架代码优先建模问题

《Entity Framework 6 Recipes》翻译系列 -----第二章 实体数据建模基础之有载荷和无载荷的多对多关系建模 (转)