2012-09-13 5 views
5

데이터 액세스를 위해 Entity Framework 5 (생성 된 POCO와 함께 데이터베이스 우선)를 사용하여 MVC4 웹 응용 프로그램을 만들고 있습니다.어떻게 Entity Framework 5 POCO 구조를 정상적으로 다시 첨부하고 저장합니까?

사용자는 응용 프로그램에서 여러 화면을 통해 문서를 작성하거나 편집합니다 ('사례 연구'라고 함). 최종 화면에 도달하면 문서가 CaseStudy POCO로 메모리에 저장되며이 구조를 데이터베이스에 저장할 때까지 모든 것이 좋습니다.

문서를 저장하기 위해 비즈니스 계층에서 사용하는 EF POCO로 매핑되는 데이터베이스 테이블을 정의한 다음 MVC 컨트롤러에서 사용합니다. 이와 같이 단명 DbContext는 POCO를 검색하고 요청간에 세션에 저장합니다.

결과적으로 저장 화면은 탐색 속성이있는이 POCO의 내용을 기존 테이블 데이터 (Category, Layout 및 Sections 테이블)에 저장하고 추가되거나 업데이트 된 데이터 (CaseStudySections 및 CaseStudy 자체)를 저장해야합니다. 따라서 모든 POCO는 새로운 것이거나 검색하는 데 사용 된 컨텍스트가 오랫동안 처리 된 것입니다. 다른 말로하면, 그들은 모두 '분리 된'것이다.

이 게시물에 대한 특이한 점은 이미 손쉽게 해결책을 찾을 수 있다는 것입니다. 문제는 그것이 부피가 크고 부서지기 쉽고 우아하지 않다는 것입니다. 아래 코드를 게시하고 있습니다. 하위 컬렉션, 명시 적 추가 및 첨부를 통한 반복에 주목하십시오. 항목 개체를 가져 와서 개별 속성을 수정 된대로 표시하여 끝에 업데이트하고, 끝 부분에 끔찍한 노래와 춤을 추가하여 AddMaterials 컬렉션을 동기화해야합니다. 이것이 EF5에서 분리 된 POCO를 다루는 데 필요한 것이면 나는 실망 할 것입니다.

여기에 뭔가가 있습니까? 이것이 베스트 프랙티스와 일치합니까? POCO 구조를 삽입하고 삽입/업데이트하는 데 좀 더 우아하고 간결한 방법이 있습니까? 일반적으로

public void SaveCaseStudy(CaseStudy caseStudy) 
{ 
    foreach (var s in caseStudy.CaseStudySections) 
    { 
     this.Entities.Sections.Attach(s.Section); 

     if (s.CreatedByRefId == default(Guid)) 
     { 
      s.CreatedByRefId = this.UserRefId; 
      s.CreatedTime = DateTime.Now; 
      this.Entities.CaseStudySections.Add(s); 
     } 
     else 
     { 
      this.Entities.CaseStudySections.Attach(s); 
      var entry = this.Entities.Entry(s); 
      entry.Property(e => e.TextData).IsModified = true; 
      entry.Property(e => e.BinaryData).IsModified = true; 
     } 

     s.LastModifiedByRefId = this.UserRefId; 
     s.LastModifiedTime = DateTime.Now; 
    } 

    foreach (var m in caseStudy.AdditionalMaterials) 
    { 
     if (m.CreatedByRefId == default(Guid)) 
     { 
      m.CreatedByRefId = this.UserRefId; 
      m.CreatedTime = DateTime.Now; 
      this.Entities.AdditionalMaterials.Add(m); 
     } 
     else 
     { 
      this.Entities.AdditionalMaterials.Attach(m); 
     } 

     m.LastModifiedByRefId = this.UserRefId; 
     m.LastModifiedByTime = DateTime.Now; 
    } 

    this.Entities.Layouts.Attach(caseStudy.Layout); 
    this.Entities.Categories.Attach(caseStudy.Category); 

    if (caseStudy.CreatedByRefId != default(Guid)) 
    { 
     this.Entities.CaseStudies.Attach(caseStudy); 
     var entry = this.Entities.Entry(caseStudy); 
     entry.Property(e => e.CaseStudyName).IsModified = true; 
     entry.Property(e => e.CaseStudyTitle).IsModified = true; 
    } 
    else 
    { 
     this.Entities.CaseStudies.Add(caseStudy); 
     caseStudy.CreatedByRefId = this.UserRefId; 
     caseStudy.CreatedTime = DateTime.Now; 
    } 

    caseStudy.LastModifiedByRefId = this.UserRefId; 
    caseStudy.LastModifiedTime = DateTime.Now; 

    if (caseStudy.CaseStudyStatus != (int)CaseStudyStatus.Personalized) 
    { 
     caseStudy.CaseStudyStatus = (int)CaseStudyStatus.PendingApproval; 
    } 

    caseStudy.ApprovedByRefId = null; 
    caseStudy.ApprovedTime = null; 
    this.Entities.SaveChanges(); 

    var existingAdditionalMaterialRefIds = caseStudy.AdditionalMaterials 
     .Select(m => m.AdditionalMaterialRefId) 
     .ToArray(); 

    var additionalMaterialsToRemove = this.Entities.AdditionalMaterials 
     .Where(m => 
      m.CaseStudyRefId == caseStudy.CaseStudyRefId && 
      !existingAdditionalMaterialRefIds.Contains(m.AdditionalMaterialRefId)) 
     .ToArray(); 

    foreach (var additionalMaterialToRemove in additionalMaterialsToRemove) 
    { 
     this.Entities.AdditionalMaterials.Remove(additionalMaterialToRemove); 
    } 

    this.Entities.SaveChanges(); 
} 

답변

3

당신이해야 할 것입니다 :

코드

는 사례 연구를 저장합니다. 분리 된 객체 그래프를 부착 할 때 수행 할 각 변경 사항에 대해 EF에 알려야합니다. 나는 당신의 코드가 단순화 될 수는 없다고 말하지는 않지만 그것이 추가되거나 수정되기를 원한다면 모든 엔티티를 다루고 상태를 설정해야한다.

Here 조금 작지만 여전히 논제에 대한 답변이 유효합니다. 짧은 시간 안에 내가 작성한 이후로 변경된 사항이 없으며 이전 API 상단에 새로운 DbContext API 만 만들어졌습니다. 지금까지 본 주제에 대한 가장 좋은 설명은 Programming Entity Framework: DbContext입니다. 단지 일에 대한

2

방법 : DB에 모델의 모든 변경 사항을 저장합니다

db.CaseStudies.Attach(caseStudy); 
db.Entry(caseStudy).State = EntityState.Modified; 
db.SaveChange(); 

.

+0

아쉽게도 작동하지 않습니다. 이 경우 우리는 DbUpdateConcurrencyException을 발생시킵니다.'Store update, insert, delete 문은 예기치 않은 행 (0)에 영향을 미쳤습니다. 엔터티가로드 된 이후에 엔터티가 수정되거나 삭제되었을 수 있습니다. ObjectStateManager 항목을 새로 고칩니다 .'. 이것은 caseStudy가 데이터베이스에 이미 존재하는 데이터 객체로 구성되어 있으므로 (명시 적으로 다시 연결해야하는 경우) 새 인스턴스이고 삽입해야하는 데이터 객체로 구성되어 있기 때문일 수 있습니다. –

관련 문제