INSERT语句与EF Core中的FOREIGN KEY约束冲突

本文关键字:FOREIGN KEY 约束 冲突 中的 Core 语句 EF INSERT | 更新日期: 2023-09-27 18:13:41

关于这个错误在不同的上下文中有许多问题,到目前为止我还无法找到一个适用于我的情况的问题。

我有一个多对多的关系,我正试图建立第三个表。这基本上是一个人对管理者的联系。所有的经理都是人,但不是所有的人都是经理,而且,每个人都有很多经理,每个经理都有很多人。在经理表中是personid。在edit下的人员控制器中,有一个将人员与经理关联起来的选项。当单击可用的管理器并单击保存时,我得到错误:

INSERT语句与外键约束"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; }
}

INSERT语句与EF Core中的FOREIGN KEY约束冲突

首先,您应该重新考虑您的模型。这个短语:

所有的经理都是人,但不是所有的人都是经理

不能转换成多对多关系。一个学生有很多课程,一个课程有很多学生,这是一个多对多关系。您的情况可以更好地翻译为:每个管理器都是一个人,这暗示了继承而不是对象组合。但是,出于学习的目的,让我们继续使用您的示例。

下面的代码(我改变了一点命名,请不要交替使用Engineer和Person,因为这会增加混淆):

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有正确的定义,实体框架就可以自己推断出来。

请记住,上面的代码只是一个多对多关系的例子,而不是一个真正好的数据库设计,但我已经张贴了它,而不是只是给你一个链接,看看你的代码和我的代码之间的差异。请按照这里的教程来更好地理解,如果这是一个项目意味着(在某些时候)不仅仅是一个学习练习,请阅读一些关于如何将数据库设计转换为代码的教程(例如如何在SQL中设计继承关系)。

您在ManagersToEngineer上有一个FK约束,因此在对ManagersToEngineer进行任何操作之前,请确保在外部表Engineer和Manager(在您的示例中为Manager)上引用的项是有效的。

更具体地说,does item。Id是否存在于您的Manager表中?