关于这个错误的背景有很多问题,到目前为止我还找不到适用于我的情况的问题。
我有很多关系,我试图用第3张桌子建立。它基本上是经理人协会的人。所有经理都是人,但不是所有人都是经理,每个人都有很多经理,每个经理都有很多人。所以在经理的表中是PersonIds。在编辑中的人员控制器是将人与经理相关联的选项。单击可用的管理器并单击“保存”时,出现错误:
INSERT语句与FOREIGN KEY约束冲突" FK_dbo.ManagerToEngineer_dbo.Manager_ManagerId"。冲突发生在数据库" PROJECTNAME_16ce3f6a2a6c4ff0b1ce147d126984ba",table" dbo.Manager",column' 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; }
}
答案 0 :(得分:0)
你对ManagersToEngineer有一个FK约束,所以在对ManagersToEngineer进行CUDing之前,请确保在外表上引用的项目Engineer和Manager(在你的情况下,Manager)是有效的。
更具体地说,您的经理表中是否存在item.Id?
答案 1 :(得分:0)
首先,您应该重新考虑您的模型。短语:
所有经理都是人,但不是所有人都是经理
不会转化为多对多关系。一个学生有很多课程,一个课程有很多学生是多对多的关系。您的情况更好地转换为:每个经理都是人,暗示继承而不是对象组成。但是,出于学习目的,让我们继续你的例子。
以下代码(我改变了一点命名,请不要互换使用工程师和人,因为它会增加混乱):
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就可以自行推断出它。
请记住,上面的代码只是多对多关系的一个例子而不是一个实际上很好的数据库设计,但我还是发布了它,而不仅仅是给你一个链接看看你和我的代码之间的区别。请按照教程here进行更好的理解,如果这是一个旨在(在某些时候)不仅仅是学习练习的项目,请阅读一些关于数据库设计如何转换为代码的教程(例如,如何设计一个SQL中的继承关系。)