2016-09-21 170 views
1

我正在向實體框架代碼優先的實體添加實體並將更改保存在上下文中。我有大學DbSet:實體框架 - DbSet包含空實體

public DbSet<University> Universities { get; set; } 

我有5個類在使用 - 期限;學院;部;大學;和學生。他們的構造方法如下:

public Student() 
{ 
    Universities = new List<University>(); 
    User = new DATABASE.User(); 
    Terms = new List<Term>(); 
} 
public University() 
{ 
    UniversityFaculties = new List<Faculty>(); 
    UniversityDepartments = new List<Department>(); 
    Students = new List<Student>(); 
} 
public Term() 
{ 
    Students = new List<Student>(); 
    Lessons = new List<Lesson>(); 
    university = new University(); 
} 
public Faculty() 
{ 
    University = new University(); 
    Students = new List<Student>(); 
} 
public Department() 
{ 
    University = new University(); 
    Students = new List<Student>(); 
} 

我從以前的表單中獲得一個學生實體(登錄該程序的學生)。當我試圖添加由組合框和文本框填充的實體時,我意識到大學DbSet正在填充我打算添加的真實實體,但也填充了一個空的大學實體。我的Id值不會自動遞增,因此我正在手動增加它們。我的代碼:

創建系實體:

Faculty f = entities.Faculties.OrderByDescending(o => o.FacultyId).FirstOrDefault(); 
int newFacultyId = (f == null ? 1 : f.FacultyId + 1); 

var faculty = new Faculty(); 
faculty.FacultyId = newFacultyId; 
faculty.FacultyName = FacultyComboBox2.SelectedItem.ToString(); 

創建部門實體:

Department d = entities.Departments.OrderByDescending(o =>o.DepartmentId).FirstOrDefault(); 
int newDepartmentId = (d == null ? 1 : d.DepartmentId + 1); 

var department = new Department(); 
department.DepartmentId = newDepartmentId; 
department.DepartmentName = DepartmentComboBox3.SelectedItem.ToString(); 

大學創建實體:

University uni = entities.Universities.OrderByDescending(o => o.UniversityId).FirstOrDefault(); 
int newUniId = (uni == null ? 1 : uni.UniversityId + 1); 

var university = new University(); 

university.UniversityId = newUniId; 
university.UniversityName = UniversityComboBox1.Text; 

university.UniversityFaculties.Add(faculty); 
university.UniversityDepartments.Add(department); 
university.Students.Add(student); 

student.Universities.Add(university); 
faculty.University = university; 
department.University = university; 
faculty.Students.Add(student); 
department.Students.Add(student); 

創建期限實體:

Term t = entities.Terms.OrderByDescending(o => o.TermId).FirstOrDefault(); 
int newTermId = (t == null ? 1 : t.TermId + 1); 

var term = new Term(); 

term.TermId = newTermId; 
term.TermTerm = int.Parse(TermComboBox1.Text); 
term.TermYear = int.Parse(YearComboBox1.Text); 

term.Students.Add(student); 
student.Terms.Add(term); 
term.university = university; 

而且我DbSet加法:

entities.Faculties.Add(faculty); 
    entities.Departments.Add(department); 
    entities.Universities.Add(university); 
    entities.Terms.Add(term); 
    entities.SaveChanges(); 

但我得到了,所以我用的try catch塊來分析異常驗證失敗的錯誤。我意識到我的大學DbSet包含一個空的大學實體。當我調試時,我意識到它們來自我爲確定實體ID而創建的實體創作。我想在大學DbSet到達空值,並刪除他們,但我不能這樣做在way.The截圖低於:

DbSet

其他DbSet的沒有這樣的疑難問題。不要」不知道該怎麼做才能擺脫這個問題。任何幫助都會很感激。謝謝。

+1

答案可能是因爲您將大學直接添加到DbSet中,但之後又通過院系和大學之間的關係。域驅動設計中的聚合根的概念將通過僅添加隱式添加相關實體的根來處理。 – strongbutgood

+1

學院,學期和部門的建造者正好創建了這所大學。看起來有些人在附加這些對象之前沒有設置,請嘗試刪除這些對象,因爲無論如何您都將大學設置爲一個整體。 – DevilSuichiro

+0

我做到了!我做了@DevilSuichiro說。我刪除了大學分配發生在構造函數和問題解決!感謝您的建議!我會盡快學習_Aggragate根域驅動設計_感謝您的評論和指導「** strongbutgood **」 –

回答

1

答案可能是因爲您將大學直接添加到DbSet中,但之後再通過院系和大學之間的關係。

當您通過DbSet.Add(entity)將實體添加到上下文中時,該實體的整個圖形將被附加到底層上下文,並且該圖形中的所有實體都將設置爲新增狀態,除非根實體已添加。那麼當你把你的學院,學期和部門與大學聯繫起來,然後把所有四個都加到上下文中時,你所獲得的不僅僅是你期望的一所大學。我不能100%確定發生了什麼,因爲正如你所說的,你手動生成Id值並且你沒有透露你的整個模型。

有三種方式我看你能解決這個問題:

1:更改關係分配使用UniversityId上學院,期限和部門,或者乾脆刪除分配和依賴的關係被作爲分配集合:

uni = entities.Universities.OrderByDescending(o => o.UniversityId).FirstOrDefault(); 
int newUniId = (uni == null ? 1 : uni.UniversityId + 1); 

var university = new University(); 
university.UniversityId = newUniId; 
university.UniversityName = UniversityComboBox1.Text; 

// these lines are sufficient to build the relationships between entities, you don't have to set both sides 
university.UniversityFaculties.Add(faculty); 
university.UniversityDepartments.Add(department); 
university.Students.Add(student); 

student.Universities.Add(university); 
// use foreign key properties to build the relationship without having large graphs when adding to context 
faculty.UniversityId = newUniId; 
department.UniversityId = newUniId; 

faculty.Students.Add(student); 
department.Students.Add(student); 

2:不要大學增加的背景下

entities.Faculties.Add(faculty); 
entities.Departments.Add(department); 
// entities.Universities.Add(university); 
entities.Terms.Add(term); 
entities.SaveChanges(); 

3:一個聚合根的域d的概念riven Design只會通過添加訪問相關實體的根實體來解決此問題。

+0

這不完全正確。 .Add語句會將樹添加到對象圖(ChangeTracker,實際上不是DbSet),除非對象已經在上下文中。這是爲了避免將多個對象附加到DbSet,而這些對象實際上並未將導航屬性與它們附加在一起。此外,您的答案建議對應的對象樹的多個來源,這將使任何Save方法不必要的複雜。 – DevilSuichiro

+0

@DevilSuichiro點指出,我會更新,以澄清正在發生的事情更準確。 – strongbutgood