2016-10-05 2 views
0

하위 엔티티가 첨부 된 간단한 개체가 있습니다. 분리 된 개체를 업데이트 할 때 자식 개체가있는 속성이 저장되지 않습니다. 이 양식에 많은 게시물을 읽었지 만 왜 업데이트되지 않는지 알 수 없습니다.분리 된 엔티티는 속성을 업데이트하지 않습니다.

엔티티를 업데이트 여기를 내부 방법을 참조하십시오

public class HtmlContent : ITextContentItem, ICreateStamp, IEditStamp, IImmutable 
{ 
    // ReSharper disable once UnusedMember.Local 
    private HtmlContent() 
    { 

    } 

    public HtmlContent(string name, string description, string text, DateTime creationDate, 
     DateTime? lastEditDate, ApplicationUser createdBy, ApplicationUser lastEditedBy) 
    { 
     this.Name = name; 
     this.Description = description; 
     this.Text = text; 
     this.CreationDate = creationDate; 
     this.LastEditDate = lastEditDate; 
     this.CreatedBy = createdBy; 
     this.LastEditedBy = lastEditedBy; 
    } 

    public HtmlContent(int id, string name, string description, string text, DateTime creationDate, 
     DateTime? lastEditDate, ApplicationUser createdBy, ApplicationUser lastEditedBy) 
     : this(name, description, text, creationDate, lastEditDate, createdBy, lastEditedBy) 
    { 
     this.Id = id; 
    } 

    public int Id { get; private set; } 

    public string Name { get; private set; } 

    public string Description { get; private set; } 

    public string Text { get; private set; } 

    public DateTime CreationDate { get; private set; } 

    public DateTime? LastEditDate { get; private set; } 

    public ApplicationUser CreatedBy { get; private set; } 

    public ApplicationUser LastEditedBy { get; private set; } 

    internal HtmlContent SetLastEditInfo(DateTime? lastEditDate, ApplicationUser lastEditedBy) 
    { 
     if ((lastEditDate.HasValue && lastEditedBy == null) || 
      (!lastEditDate.HasValue && lastEditedBy != null)) 
     { 
      throw new InvalidOperationException($"{nameof(lastEditDate)} and {nameof(lastEditedBy)} must be used together"); 
     } 

     return new HtmlContent(this.Id, this.Name, this.Description, this.Text, this.CreationDate, lastEditDate, this.CreatedBy, lastEditedBy); 
    } 

    internal HtmlContent UpdateHtmlContent(string name, string description, string text) 
    { 
     return new HtmlContent(this.Id, name, description, text, this.CreationDate, this.LastEditDate, this.CreatedBy, this.LastEditedBy); 
    } 
} 

을 여기에 업데이트 방법을 참조하십시오 :

public async Task Edit(int id, string name, string description, string text) 
{ 
    try 
    { 
     var content = await this.WithId(id); 
     this.db.Entry(content).State = EntityState.Detached; 

     var currentDate = DateTime.UtcNow; 
     var lastEditedBy = this.userProvider.GetCurrentUser(); 

     content = content.SetLastEditInfo(currentDate, lastEditedBy); 
     content = content.UpdateHtmlContent(name, description, text); 

     this.db.Entry(content).State = EntityState.Modified; 
     await this.db.SaveChangesAsync(); 
    } 
    catch (System.Data.Entity.Validation.DbEntityValidationException ex) 
    { 
     var errors = ex.EntityValidationErrors; 
     throw; 
    } 
} 

다른 모든 속성이 잘 업데이트됩니다. LastEditedBy 만 업데이트되지 않습니다. Create 메서드에서 CreatedBy이 올바르게 작동하는 것은 데이터베이스에 저장된 새 엔터티이기 때문입니다. ApplicationUser 속성에는 코드에서 먼저 생성 된 데이터베이스에 외래 키가 있습니다.

답변

0

솔루션은 모델의 외래 키 속성을 만드는 것입니다 (이 데이터베이스에서 외래 키가 이미 있지만, 첫 번째 코드로 생성). 그런 식으로 LastEditedBy 사용자가있는 경우 생성자에서 속성을 설정할 수 있습니다.

public class HtmlContent : ITextContentItem, ICreateStamp, IEditStamp, IImmutable 
{ 
    // ReSharper disable once UnusedMember.Local 
    private HtmlContent() 
    { 

    } 

    public HtmlContent(string name, string description, string text, DateTime creationDate, 
     DateTime? lastEditDate, ApplicationUser createdBy, ApplicationUser lastEditedBy) 
    { 
     this.Name = name; 
     this.Description = description; 
     this.Text = text; 
     this.CreationDate = creationDate; 
     this.LastEditDate = lastEditDate; 
     this.CreatedBy = createdBy; 

     this.LastEditedBy = lastEditedBy; 
     this.LastEditedById = LastEditedBy?.Id; // Set the id if it isn't null 
    } 

    public HtmlContent(int id, string name, string description, string text, DateTime creationDate, 
     DateTime? lastEditDate, ApplicationUser createdBy, ApplicationUser lastEditedBy) 
     : this(name, description, text, creationDate, lastEditDate, createdBy, lastEditedBy) 
    { 
     this.Id = id; 
    } 

    public int Id { get; private set; } 

    public string Name { get; private set; } 

    public string Description { get; private set; } 

    public string Text { get; private set; } 

    public DateTime CreationDate { get; private set; } 

    public DateTime? LastEditDate { get; private set; } 

    public ApplicationUser CreatedBy { get; private set; } 

    [ForeignKey("LastEditedById")] // Set the foreign key to existing property 
    public ApplicationUser LastEditedBy { get; private set; } 

    // Use a property in the model for saving and not just a property generated by code first in the database 
    public string LastEditedById { get; private set; } 

    internal HtmlContent SetLastEditInfo(DateTime? lastEditDate, ApplicationUser lastEditedBy) 
    { 
     if ((lastEditDate.HasValue && lastEditedBy == null) || 
      (!lastEditDate.HasValue && lastEditedBy != null)) 
     { 
      throw new InvalidOperationException($"{nameof(lastEditDate)} and {nameof(lastEditedBy)} must be used together"); 
     } 

     return new HtmlContent(this.Id, this.Name, this.Description, this.Text, this.CreationDate, lastEditDate, this.CreatedBy, lastEditedBy); 
    } 

    internal HtmlContent UpdateHtmlContent(string name, string description, string text) 
    { 
     return new HtmlContent(this.Id, name, description, text, this.CreationDate, this.LastEditDate, this.CreatedBy, this.LastEditedBy); 
    } 
} 
4

당신이 그것을하고있는이 방법을 수행 해본 적이 있기 때문에 제가 틀릴 수도 있지만 나는 모델 여러 문제를 볼 수 있습니다.

1. 데이터 모델은 개인 setter를 가지고 있으며, 매개 변수가없는 생성자가 없습니다.
데이터 모델은 공용 설정자와 getter 및 매개 변수없는 생성자가있는 일련의 속성이어야합니다. 이렇게하면 EF가 탐색 속성을 프록시하여 속성이 설정되었을 때 '알 수 있습니다. 모델을 채우는

2. 귀하의 코드는 모델 자체 안에 있습니다.
큰 문제는 아니지만 앞으로는 일반 저장소와 같은 것을 사용할 수 없습니다. 모든 모델은 을 알고 있습니다. 읽을 수없는 코드로 이어질 수있는 자신을 조작하는 방법은입니다. 이 100 % 중요하지 않습니다 동안 저장소 패턴

3.을 확인하는 것은 외래 키가
다시 탐색 속성에 대해 정의하는 데, 그것은 당신이 먼저 데이터베이스에서 선택하지 않고 관련 기관을 설정할 수 있습니다 . 관련 엔티티의 ID를 설정할 수 있습니다.

4. EF에 대한 속성
휴식 추적을 설정하는 새로운 엔티티를 생성하고, 또한 기업의 모든 참조 무결성을 중단해서는 안된다. 엔티티가 수명 기간 동안 동일한 객체가되기를 원합니다. 따라서 개체를 잃지 않고 속성을 수정할 수 있으며 EF로 추적 할 수 있습니다.

나의 제안은 이것이다 :

public class HtmlContent 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string Description { get; set; } 

    public string Text { get; set; } 

    public DateTime CreationDate { get; set; } 

    public DateTime? LastEditDate { get; set; } 

    public int CreatedById { get; set; } 

    public int LastEditedById { get; set; } 

    public ApplicationUser CreatedBy { get; set; } 

    public ApplicationUser LastEditedBy { get; set; } 
} 


public HtmlContentService 
{ 
    public async Task Edit(int id, string name, string description, string text) 
    { 
     try 
     { 
      var content = await this.WithId(id); 

      // no need to detach the object if you arent disposing the context 
      //this.db.Entry(content).State = EntityState.Detached; 

      var currentDate = DateTime.UtcNow; 
      var lastEditedBy = this.userProvider.GetCurrentUser(); 

      // these methods could just be moved into this method 
      this.SetLastEditInfo(content, currentDate, lastEditedBy); 
      this.UpdateHtmlContent(content, name, description, text); 

      this.db.Entry(content).State = EntityState.Modified; 
      await this.db.SaveChangesAsync(); 
     } 
     catch (System.Data.Entity.Validation.DbEntityValidationException ex) 
     { 
      var errors = ex.EntityValidationErrors; 
      throw; 
     } 
    } 

    private void SetLastEditInfo(
     HtmlContent content, 
     DateTime lastEditDate, 
     ApplicationUser lastEditedBy) 
    { 
     if ((lastEditDate.HasValue && lastEditedBy == null) || 
      (!lastEditDate.HasValue && lastEditedBy != null)) 
     { 
      throw new InvalidOperationException(
       $"{nameof(lastEditDate)} and {nameof(lastEditedBy)} must be used together"); 
     } 

     content.LastEditDate = lastEditDate; 
     content.LastEditedBy = lastEditedBy; 
    } 

    private void UpdateHtmlContent(
     HtmlContent content, 
     string name, 
     string description, 
     string text) 
    { 
     content.Name = name; 
     content.Description = description; 
     content.Text = text; 
    } 
} 
+1

나는 이유 # 4에 내 내기를 넣어 것입니다. –

+0

먼저 반응에 감사드립니다. 거의 완전한 모델로 질문을 업데이트했습니다. 나는 속성과 같은 필요한 정보를 제거하지 않았습니다. 나는'private' 인 생성자를 가지고 있습니다.개인 집합을 사용하는 이유에 대한 속성을 만들었습니다. 그 이유는 개체 외부에서 값을 설정할 수 없기 때문입니다. 객체는 유지 보수 방법에 대한 논리를 가져야하며 다른 일부 표면은 유지 보수하지 말아야합니다. 한 클래스에서 변경할 수 있다면 여러 클래스로 변경할 수 있습니다. 그 후, 코드 복제가 시작됩니다. 나는 또한 나의 실체가 분리되었다고 말했다. 추적을 원하지 않기 때문입니다. –

+0

문제에 대한 해답을 추가합니다. 이제 객체는 객체 자체의 외부에서 '불변'상태가됩니다. 나를 올바른 방향으로 가리켜 주셔서 감사합니다. –

관련 문제