2016-09-21 15 views
1

DbSet에 엔터티를 추가하고 Entity Framework Code First의 컨텍스트에서 변경 내용을 저장하려고합니다. 나는 대학을 가지고있다. DbSet :Entity Framework - DbSet에 Null 엔터티가 포함됨

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>(); 
} 

이전 양식의 학생 항목 (프로그램에 로그인 한 학생)을받습니다. 콤보 박스와 텍스트 박스로 채워진 엔티티를 추가하려고 할 때, Universities 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(); 

그러나 나는 예외를 분석하는 시도의 catch 블록을 사용하므로 검증 오류 실패 얻었다. 내 대학교 DbSet에 빈 대학 엔티티가 있다는 것을 알게되었습니다. 내가 디버깅 할 때 엔티티의 ID를 결정할 목적으로 만든 엔티티 생성에서 온다는 것을 깨달았습니다. 나는 대학 DbSet에 null 값에 도달하고 그들을 제거하려하지만 난 그 길이야 스크린 샷에서 그것을 할 수있는 다음과 같습니다 :

DbSet

다른 DbSet의이하지 않아도 문제 야 돈 ' 그 문제를 없애기 위해 무엇을해야하는지 알지. 도움이된다면 고마워. 고마워.

+1

대답은 대학을 DbSet에 직접 추가하는 것이지만 학부와 대학의 관계를 통해 다시 추가한다는 것입니다. 도메인 기반 디자인의 총계 루트 개념은 암시 적으로 관련 엔티티를 추가하는 루트 만 추가하여이를 처리합니다. – strongbutgood

+1

학부의 생성자, 학기 및학과가이 대학을 정확하게 만듭니다. 이 중 일부는 이러한 객체를 첨부 할 때까지 설정되지 않은 것으로 보입니다. 어쨌든 대학 전체를 설정했기 때문에 이러한 할당을 제거해보십시오. – DevilSuichiro

+0

나는 그것을했다! @DevilSuichiro가 말했듯이 저는했습니다. 나는 생성자와 문제 해결에서 일어나는 대학 과제를 제거했습니다! 조언 주셔서 감사합니다! 내가 할 수있는 한 빨리 도메인 구동 디자인의 _Aggragate 루트를 배울 것입니다. 귀하의 의견과 지침에 대해 감사드립니다. "** strongbutgood **" –

답변

1

대답은 대학을 DbSet에 직접 추가하는 것이지만 학부와 대학 간의 관계를 통해 다시 추가한다는 것입니다.

DbSet.Add(entity)을 통해 컨텍스트에 엔터티를 추가하면 해당 엔터티의 전체 그래프가 기본 컨텍스트에 연결되고 해당 그래프의 모든 엔터티는 추가 된 상태가됩니다 (루트 엔터티가 이미 추가 된 경우 제외). 그러면 학부, 학기 및학과를 대학과 연결 한 다음 네 가지를 모두 문맥에 추가하면 예상 한 대학보다 더 많은 것을 얻을 수 있습니다. ID 값을 수동으로 생성하고 전체 모델을 공개하지 않았다는 이유로 100 % 확신 할 수 없습니다.

나는 당신이이 문제를 해결 할 수 있습니다 볼 세 가지 방법이 있습니다

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 : 도메인 D의 집계 루트의 개념 : 문맥

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

세에 대학을 추가하지 마십시오 riven Design은 관련 엔티티가 액세스되는 루트 엔티티 만 추가하여이를 처리합니다.

+0

이것은 완전히 사실이 아닙니다. .Add 문은 개체가 이미 컨텍스트에 있지 않으면 트리를 개체 그래프 (ChangeTracker, 실제로 DbSet 아님)에 추가합니다. 이는 DbSet에 여러 객체를 연결하는 것을 피하기위한 것으로, 실제로는 탐색 속성을 객체에 첨부하지 않습니다. 또한, 당신의 대답은 대응하는 객체 트리의 여러 소스를 제안하며, 이는 Save 메소드를 불필요하게 복잡하게 만듭니다. – DevilSuichiro

+0

@DevilSuichiro 지적했다. 더 정확하게 일어나고 있는지 명확히하기 위해 업데이트 할 것이다. – strongbutgood