2017-07-27 62 views
-4

我需要在一個DbSet.Add調用中插入一個實體與相關實體。EF6 - 僅當通過導航屬性插入具有相關實體的實體時發生錯誤

一對多的課程和CourseProfesor之間(CourseProfesor是實體連接課程和Profesors)

實體:

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(實體)執行CreateCommand這將反過來調用

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

的例外,我得到:

到數據庫的更改已成功提交,但在更新時發生錯誤對象上下文。 ObjectContext可能處於不一致的狀態。內部異常消息:發生參照完整性約束衝突:關係一端的'Course.ID'的屬性值與另一端的'CourseProfesor.CourseID'的屬性值不匹配

如果我還不知道課程ID,那麼如何分配CourseProfesor.CourseID,因爲兩者都是新實體?
正如您在控制器代碼中看到的那樣,我曾經通過僅設置導航屬性來解決這個問題,並且EF會相應地自動填充外鍵。
這一點很重要:這是對EF5做工精細,我更新到EF6

任何線索,爲什麼EF6拋出該異常而EF5後仍未得到了錯誤?以及如何解決這個問題,而無需先創建課程,然後創建CourseProfesor關係實體?

+0

你需要建立你的實體映射/配置和實體類。 EF6可以很好地處理這些問題,但是您必須確保它具有關於您的實體關係以及圍繞關鍵生成的規則的足夠信息。 –

+0

謝謝你的提示。我用實體和配置編輯了這個問題。對不起,這是我的第一個問題 – Lucio

回答

0

幾件事情用突出:

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

當使用導航屬性我脫離過往定義在實體FKS領域了,但如果你需要定義它們,你應該避免設置它們。僅使用導航屬性。設置FK可能會產生誤導,因爲如果您將此課程與課程職位一起傳授並使用,則會有Professor 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); 

嘗試刪除冗餘映射。

此外,鏈接表的定義具有一個ID作爲PK,但沒有設置生成選項。這兩個FK的設置順序= 0和順序= 1,這看起來很奇怪,不考慮PK?

除此之外,我不能說我喜歡那個門面模式。爲了消除這種可能性,如果您訪問DB上下文課程DBSet會發生什麼?

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

感謝您回覆@Steve。我嘗試了一些建議,但沒有運氣:( - 刪除「CourseID = 0」部分並不能解決問題,因爲它無論如何都會使用該默認值,因爲它是不可空的int - 缺少的屬性DatabaseGeneratedOption.Identity是不是問題 - 刪除冗餘映射也不起作用,事實上,之前沒有,我只是爲了防止EF6 中的問題而添加 - 我沒有但是Facade只是將POCO實體作爲參數傳遞給命令 – Lucio

+0

我意識到Facade會使讀取變得複雜,但是通過調用'context.Set(type).Add(entity)'或'Database將實體插入到另一個對象中。條目(entidad).State = EntityState.Added'不應該是一個問題,事實上這就是Repository模式的作用。在控制器中的所有這種多次插入都會拋出t他同樣的例外,但在EF4和EF5中工作正常... – Lucio

相關問題