C# 首先使用EF代码建模员工助理关系

C# 首先使用EF代码建模员工助理关系,c#,asp.net-mvc,ef-code-first,entity-framework-6,self-referencing-table,C#,Asp.net Mvc,Ef Code First,Entity Framework 6,Self Referencing Table,简而言之,以下是业务需求: 所有员工都需要存储在数据库中 有些员工有助手,有些没有 有些员工有不止一名助手 助理也是雇员 显然存在一种自我参照的情况。但与典型的“员工经理”情况不同的是,这里一个员工可以有0个或多个助理。因此,员工和员工的助手的组合需要存储在一个单独的表中,员工和员工助手之间的一对多关系中。但我对如何首先在EntityFramework6代码中对此进行建模感到困惑 我从这个开始: public class Employee { public int Id { get;

简而言之,以下是业务需求:

  • 所有员工都需要存储在数据库中
  • 有些员工有助手,有些没有
  • 有些员工有不止一名助手
  • 助理也是雇员
显然存在一种自我参照的情况。但与典型的“员工经理”情况不同的是,这里一个员工可以有0个或多个助理。因此,员工和员工的助手的组合需要存储在一个单独的表中,员工员工助手之间的一对多关系中。但我对如何首先在EntityFramework6代码中对此进行建模感到困惑

我从这个开始:

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class EmployeeAssistant
{
   [ForeignKey("Employee")]
   public int EmployeeId { get; set; }
   public virtual Employee Employee { get; set; }

   [ForeignKey("Assistant")]
   public int AssistantId { get; set; }
   public virtual Employee Assistant { get; set; }
}
但是我在
更新数据库
命令期间出错:

在表“EmployeeAssistant”上引入外键约束“FK_dbo.EmployeeAssistant_dbo.Employee_EmployeeId”可能会导致循环或多个级联路径。指定“在删除时不执行操作”或“在更新时不执行操作”,或修改其他外键约束

我错过了什么?我是否应该以不同的方式处理此问题?

基于此链接

如果用代码删除
EmployeeAssistant
,似乎会导致两个级联删除路径

我建议采用如下结构:

编辑后

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<EmployeeAssistant> Assistants { get; set; } //if an employee has no assistants this List can easily just be empty
    OR
    public ICollection<EmployeeAssistant> Assistants { get; set; } // depending on your architecture, choose the one that would suit you better
}
public class EmployeeAssistant
{
   [ForeignKey("Employee")]
   public int EmployeeId { get; set; } //this is the employee who 'has' this assistant
   public virtual Employee Employee { get; set; }

   public int Id { get; set; }  //this is the assistant's own information - identical to employee's basic info
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

我知道第二种方法非常混乱,可能不适合您的需要,但就我个人而言,我总是先创建数据库表,然后“从数据库生成模型”,因此我对代码优先的方法缺乏经验。

因为每个员工可能有一个或多个助理(每个助理将有一个或多个员工)所有人都是员工,最简单的解决方案是一个类,包含两个助手和员工集合,关系将由框架管理:

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<Employee> Assistants { get; set; }
    public ICollection<Employee> Employees { get; set; }
}
公共类员工
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共ICollection助手{get;set;}
公共ICollection雇员{get;set;}
}
当您使用PackageManager控制台添加迁移时,它将自动创建两个表,一个用于员工,另一个用于多对多关系

然后,您所要做的就是使用Include扩展方法查找相关助理和/或员工

其中(x=>x.Id==Id)。包括(x=>x.Assistants)。FirstOrDefault()

和/或

其中(x=>x.Id==Id)。包括(x=>x.Employees)


这可能会对你有所帮助:嗯,但是你怎么知道哪个助手和哪个员工一起去呢?如果EmployeeAssistant实体只有
Employee
引用,则这将在数据库
EmployeeAssistant
中创建一个带有
Id
EmployeeId
字段的表。因此,将员工与助手联系起来是缺少数据的。对吧?我在你修改后重读了你的答案。我很欣赏你的大脑!但是,第一种方法意味着我必须复制EmployeeAssistant类中的所有Employee属性,这没有意义,因为EmployeeAssistant是一名员工自己。第二种方法不起作用,因为它只处理一个助理案例,而不处理多个助理。那么在第二种方法中添加一个员工助理列表就可以了?e、 g.
publicslist助手{get;set;}
Hmm,我认为这不管用,但它确实管用!我唯一的问题是,生成的多对多表的名称为
EmployeeEmployee
,字段为
Employee\u Id
Employee\u Id1
。有没有一种方法可以通过数据注释(最好是)或流畅的映射来控制这些元素的名称?您不必更改这些字段,因为您不会使用它,框架将为您完成肮脏的工作:)顺便说一句,在您从employees表中删除一个实体之前,您必须清除它与其他实体的关系。是的,我知道我不必这样做,但我需要数据库本身有意义,因为它将用于报告和其他潜在的直接查询。我不能把它当作“黑匣子”数据持久化。我已经找到了如何使用fluent映射实现这一点,只是不确定如何使用数据注释实现这一点,如果可能的话。当我有机会的时候,我会发布一个更详细的答案。
public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<Employee> Assistants { get; set; }
    public ICollection<Employee> Employees { get; set; }
}