INSERT語句與EF Core中的FOREIGN KEY約束衝突

asp.net-core c# entity-framework-core

關於這個錯誤的背景有很多問題,到目前為止我一直無法找到適用於我的情況的問題。

我有很多關係,我試圖用第3張桌子建立。它基本上是經理人協會的人。所有經理都是人,但不是所有人都是經理,每個人都有很多經理,每個經理都有很多人。所以在經理的表中是PersonIds。在編輯中的人員控制器是將人與經理相關聯的選項。單擊可用的管理器並單擊“保存”時,出現錯誤:

INSERT語句與FOREIGN KEY約束“FK_dbo.ManagerToEngineer_dbo.Manager_ManagerId”衝突。衝突發生在數據庫“PROJECTNAME_16ce3f6a2a6c4ff0b1ce147d126984ba”,表“dbo.Manager”,列'ManagerId'中。該語句已終止。

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

熱門答案

首先,您應該重新考慮您的模型。詞組:

所有經理都是人,但不是所有人都是經理

不會轉化為多對多的關係。一個學生有很多課程,一個課程有很多學生是多對多的關係。你的情況轉化得更好:每個經理都是一個暗示繼承而非對象構成的人。但是,出於學習目的,讓我們繼續你的例子。

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

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具有正確的定義,Entity Framework可以自行推斷出它。

請記住,上面的代碼只是多對多關係的一個例子,而不是一個真正好的數據庫設計 ,但我還是發布了它,而不僅僅是給你一個鏈接,看看你的代碼和我的代碼之間的區別。請按照此處的教程進行更好的理解,如果這是一個旨在(在某些時候)不僅僅是學習練習的項目,請閱讀有關數據庫設計如何轉換為代碼的一些教程(例如,如何在SQL中設計繼承關係) )。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow