2016-09-21 169 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