EF6 - 只有导航属性插入具有相关实体的实体时出错

时间:2017-07-27 21:39:46

标签: c# asp.net-mvc entity-framework

我需要在一个DbSet.Add调用中插入一个包含相关实体的实体。

课程与CourseProfesor之间的一对多(CourseProfesor是连接课程和教授的实体)

实体:

public class Course
{
    public Course() { }
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    ...
    public virtual ICollection<CourseProfesor> Profesors { get; set; }
}

public class CourseProfesor
{
    public CourseProfesor() { }
    [Key]
    public int ID { get; set; }
    [Required, Index, Column(Order = 0)]
    public int CourseID { get; set; }
    [Required, Index, Column(Order = 1)]
    public int ProfesorID { get; set; }
    ...
    [ForeignKey("CourseID")]
    public virtual Course Course { get; set; }
    [ForeignKey("ProfesorID")]
    public virtual Profesor Profesor { get; set; }
}

映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Course>().HasMany(x => x.Profesors).WithRequired(x => x.Course);
    modelBuilder.Entity<CourseProfesor>().HasRequired(x => x.Course).WithMany(x => x.Profesors);
    modelBuilder.Entity<CourseProfesor>().HasRequired(x => x.Profesor).WithMany(x => x.Courses);
}

控制器:

public ActionResult Add(Course course, int profesorId = 0)
{
   if (profesor > 0)
   {
       course.Profesors = new List<CourseProfesor>();
       course.Profesors.Add(new CourseProfesor() { Course = course, CourseID = 0, ProfesorID = profesorId, From = DateTime.Now, Role = ... });
   }
   Facade.Create(course);
   return Json(new {statusText = "Course Added"});
}

Facade.Create(entity)执行一个CreateCommand,它将依次调用

DbContext.Set(entity.GetType()).Add(entity)

我得到的例外:

  

已成功提交对数据库的更改,但更新对象上下文时发生错误。 ObjectContext可能处于不一致状态。内部异常消息:发生了参照完整性约束违规:&#39; Course.ID&#39;的属性值。在一段关系的一端与&#39; CourseProfesor.CourseID&#39;的财产价值不匹配。在另一端

如果我还不知道课程的ID,如何分配CourseProfesor.CourseID,因为两者都是新实体?
正如您在控制器代码中看到的那样,我曾经通过设置导航属性来解决这个问题,EF会相应地自动填充外键。
这很重要:这在EF5上工作正常,我在更新到EF6后出现了错误

任何线索为什么EF6抛出异常而EF5没有?以及如何解决它而无需先创建课程,然后再创建CourseProfesor关系实体?

1 个答案:

答案 0 :(得分:0)

有几件事情很突出:

course.Profesors.Add(new CourseProfesor() { Course = course, CourseID = 0, ProfesorID = profesorId, From = DateTime.Now, Role = ... });

使用导航属性时,我避免在实体中定义FKs字段,但如果需要定义它们,则应避免设置它们。仅使用导航属性。设置FK可能会产生误导,因为如果您要将此课程与其课程教授一起使用并使用它,则会有一个教授ID集,但没有教授参考。

关于您的具体问题,可能的问题是上面设置的CourseID = 0,以及Course和CourseProfessor之间的双向映射。

modelBuilder.Entity<Course>().HasMany(x => x.Profesors).WithRequired(x => x.Course);
//modelBuilder.Entity<CourseProfesor>().HasRequired(x => x.Course).WithMany(x => x.Profesors);
modelBuilder.Entity<CourseProfesor>().HasRequired(x => x.Profesor).WithMany(x => x.Courses);

尝试删除该冗余映射。

此外,链接表的定义具有作为PK的ID,但未使用生成选项进行设置。两个FK设置为​​Order = 0和Order = 1,看起来奇怪而不考虑PK?

除此之外,我不能说我喜欢那种立面图案。为了消除这种可能性,如果你去DB Context Courses DBSet会怎么样?

context.Courses.Add(course);
context.SaveChanges();