2016-10-18 92 views
0

在有關此錯誤的各種上下文中有許多問題,到目前爲止,我一直無法找到適用於我的情況的問題。INSERT語句與EF核心中的FOREIGN KEY約束衝突

我有一個多對多的關係,我試圖建立一個第三表。這基本上是經理協會的一個人。所有管理者都是人,但並不是所有人都是管理者,而且每個人都有很多管理者,每個管理者都有很多人。所以在經理的桌子上是PersonIds。在編輯中的人員控制器是將人員與經理關聯的選項。當點擊可用管理者和點擊保存,我得到的錯誤:

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ManagerToEngineer_dbo.Manager_ManagerId". The conflict occurred in database "PROJECTNAME_16ce3f6a2a6c4ff0b1ce147d126984ba", table "dbo.Manager", column 'ManagerId'. The statement has been terminated.

SaveChanges方法導致這個錯誤:

 [HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Edit(PersonViewModel person) 
     { 
      if (ModelState.IsValid) 
      { 
       //var MyPerson = db.people.Find(person.PersonId); 
       //MyPerson.FirstName = person.FirstName; 
       //MyPerson.LastName = person.LastName; 
       foreach (var item in db.ManagersToEngineers) 
       { 
        if (item.EngineerId == person.PersonId) 
        { 
         db.Entry(item).State = EntityState.Deleted; 
        } 
       } 

       foreach (var item in person.EngineerManagers) 
       { 
        if (item.Checked) 
        { 
         db.ManagersToEngineers.Add(new ManagerToEngineer() { EngineerId = person.PersonId, ManagerId = item.Id }); 
        } 
       } 
       //db.Entry(person).State = EntityState.Modified; 
       db.SaveChanges(); 
       return RedirectToAction("Index"); 
      } 
      return View(person); 
     } 

相關機型:

public class ManagerToEngineer 
    { 
     [Key] 
     public int ManagerToEngineerId { get; set; } 

     [Required] 
     [ForeignKey("engineer")] 
     public int EngineerId { get; set; } 

     [Required] 
     [ForeignKey("manager")] 
     public int ManagerId { get; set; } 

     public virtual Person engineer { get; set; } 
     public virtual Manager manager { get; set; } 

    } 

public class Manager 
{ 
    [Key] 
    public int ManagerId { get; set; } 

    [Required] 
    [ForeignKey("person")] 
    public int EngineerId { get; set; } 

    public virtual Person person { get; set; } 
    public ICollection<ManagerToEngineer> ManagersToEngineers { get; set; } 
} 

public class PersonViewModel 
{ 
    public int PersonId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    [Display(Name = "Managers")] 
    public List<CheckBoxViewModel> EngineerManagers { get; set; } 
} 

public class CheckBoxViewModel 
{ 
    public int Id { get; set; } 
    public string FullName { get; set; } 
    public bool Checked { get; set; } 
} 
+0

您應該查看以下有關EF Core中的多對多關係的文檔:https://docs.efproject.net/en/latest/modeling/relationships.html#many-to-many。 –

回答

0

你有一個FK對ManagersToEngineer進行約束,以便在Cursing ManagersToEngineer上的任何內容之前,確保在外部表上引用的項目Engineer和Manager(在您的情況下爲Manager)是有效的。

更具體地說,item.Id是否存在於Manager表中?

+0

item.Id是指CheckBoxViewModel。 –

+0

什麼項目。Id是指CheckBoxViewModel無關緊要。重要的是item.Id的值是否存在於Managers.Select(p => p.ManagerId).ToList()中。 – Nathan

0

首先,你應該重新考慮你的模型。短語:

All managers are people but not all people are managers

不會轉化爲多對多的關係。一個學生有很多課程,一門課程有很多學生是多對多的關係。你的情況翻譯得更好,因爲:每個經理是一個人暗示繼承而不是對象組成。但是,爲了學習目的,我們繼續以您的示例爲例。

下面的代碼(我已經改變了命名一點點,請不要使用工程師和人互換,因爲它增加了混亂):

public class Person 
{ 
    public Person() 
    { 
     Managers = new HashSet<Manager>(); 
    } 

    [Key] 
    public int PersonId { get; set; } 

    public string Name { get; set; } 

    public virtual ICollection<Manager> Managers { get; set; } 
} 

public class Manager 
{ 
    public Manager() 
    { 
     Persons = new HashSet<Person>(); 
    } 

    [Key] 
    public int ManagerId { get; set; } 

    public virtual ICollection<Person> Persons { get; set; } 
} 

public class CompanyContext : DbContext 
{ 
    public DbSet<Person> Persons { get; set; } 

    public DbSet<Manager> Managers { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Person>() 
      .HasMany(p => p.Managers).WithMany(m => m.Persons) 
      .Map(t => t.MapLeftKey("PersonID") 
       .MapRightKey("ManagerID") 
       .ToTable("PersonToManager")); 
    } 
} 

你會發現爲什麼這不是一個好的設計執行當插入:

static void Main(string[] args) 
    { 
     using (var db = new CompanyContext()) 
     { 
      // add a person 
      var person = new Person() { Name = "Joe" }; 
      db.Persons.Add(person); 

      // "make" him manager 
      var manager = new Manager(); 
      manager.Persons.Add(person); 
      db.Managers.Add(manager); 

      db.SaveChanges(); 
     } 

     Console.ReadKey(); 
    } 

上面的代碼編譯和運行應該(但因爲我有一些SqlLocalDb問題,我無法測試它)。請注意,我不需要爲關聯表顯式創建類,實體框架可以自行推斷出您的modelBuilder具有正確的定義。

請記住上面的代碼只是許多一對多的關係,而不是實際良好的數據庫設計的例子,但我已經發布也無妨,而不是僅僅給你一個鏈接,看到了差距你的代碼和我的代碼之間。請遵循教程here以獲得更好的理解,如果這是一個旨在(在某些情況下)不僅僅是學習練習的項目,請閱讀關於數據庫設計如何轉換爲代碼的一些教程(例如,如何在SQL中設計繼承關係)。

+0

但事情是,所有人都有很多經理,所有經理都有很多人,但所有經理都是人。 –

+0

什麼是哈希集?經理不會繼承人,我曾經這樣認爲,但是我意識到我需要每一個用戶都先成爲一個人,並且我可以讓管理員讓他們成爲經理。 –

+0

也許我並沒有完全理解你想要達成的目標,但這似乎是繼承的一個教科書範例。考慮像這樣的層次結構:Person - 抽象類,由Manager和Employer擴展。然後你會爲每個經理保留一份僱員名單,而他自己也是一個人。先設計數據庫,稍後再擔心DAL。看看[this](https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework- in-an-asp-net-mvc-application) – AlinG

相關問題