3

這裏有業務需求,簡言之:建模員工-助理(S)與EF代碼優先關係

  • 所有員工需要被存儲在數據庫中
  • 有些員工有助理 ,有的沒有
  • 有些員工有一個以上的助理
  • 助理是員工,以及

顯然有一點自我參照的情況。但與典型的「員工經理」情況的不同之處在於,這裏一名員工可以有0個或多個助理。所以,員工和員工的助理需要的組合存儲在一個單獨的表中一個一對多的關係員工EmployeeAssistant之間。但是我很困惑如何在Entity Framework 6 Code First中對此進行建模。

我開始用這樣的:

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; } 
} 

但我Update-Database命令時出現錯誤:

表 'EmployeeAssistant' 可能會導致循環引進國外KEY約束 'FK_dbo.EmployeeAssistant_dbo.Employee_EmployeeId'或多個級聯路徑。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY約束。

我錯過了什麼?我應該採取不同的方式嗎?

+2

也許這將幫助你:http://stackoverflow.com/ questions/14489676/entity-framework-how-to-solve-foreign-key-constraint-may-cause-cycles-or-multi –

回答

0

基於此鏈接Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?

,如果你刪除你的代碼的EmployeeAssistant看來,它會導致2級聯刪除路徑

我建議這樣的結構,因爲這樣:

編輯

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; } 
} 

一會兒腦難以置信的後

後,我甚至想到了一個可能性,你只需要1級,員工,但它包括表示該員工是否爲助理的bool IsAssistant,以及具有此助理的員工的員工ID AssistantEmployeeId。 例如:

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

我知道這第二種方法是非常混亂,可能不適合您的需要,但我個人總是先創建數據庫表,然後做「從數據庫生成模式」,所以我在經驗不足代碼優先的方法。

+0

嗯,但你怎麼知道哪個助手跟哪個員工在一起?如果EmployeeAssistant實體只有'Employee'引用,那麼這將在數據庫'EmployeeAssistant'中創建一個具有'Id'和'EmployeeId'字段的表。因此,它缺少將員工綁定到助理的數據。對? – Jiveman

+0

我在編輯後重新閱讀您的答案。我欣賞這個令人難以置信的大腦!然而,第一種方法意味着我必須複製EmployeeAssistant類中的所有Employee屬性,並且這沒有意義,因爲EmployeeAssistant本身就是Employee。第二種方法不起作用,因爲它只處理一個助理案件,而不是多個助理。 – Jiveman

+0

然後在第二種方法中添加一個EmployeeAssistantIDs列表可以做到這一點嗎?例如'公開列表 AssistantIDs {get;組; }' –

1

因爲每個員工可能有一個或多個助理(每個助理將有一個或多個員工)並且全部都是員工,最簡單的解決方案是一個類,其中有兩個助理和員工的集合,關係將由框架:

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; } 
} 

當您使用包管理器控制檯添加遷移它會自動創建兩個表,一個員工,另一個是多對多的關係。

那麼您所要做的就是使用包含擴展方法找到相關助理和/或員工。

db.Employees.Where(X => x.Id == ID).INCLUDE(X => x.Assistants).FirstOrDefault()

和/或

db.Employees.Where(X => x.Id == ID).INCLUDE(X => x.Employees).FirstOrDefault()

+0

嗯,沒想到這會起作用,但它呢!我唯一的問題是,生成的多對多表的名稱爲EmployeeEmployee,其中的字段爲Employee_Id和Employee_Id1。有沒有辦法通過數據註釋(最好)或使用Fluent映射來控制這些元素的名稱? – Jiveman

+0

您不必更改這些字段,因爲您不會使用它,框架將爲您執行骯髒的工作:) btw,在從employees表中刪除實體之前,您必須清除其與其他實體的關係。 – Ziyad

+0

是的,我知道我不需要,但我需要數據庫本身才有意義,因爲它將用於報告和其他潛在的直接查詢。我不能僅僅將它用作「黑匣子」數據持久性。我發現如何用流利的映射來做到這一點,只是不確定如何使用數據註釋來做到這一點,如果它甚至是可能的。當我有機會時,會提供更多細節的答案。 – Jiveman