5

'낙관적 인 업데이트'의 경우 EF 읽기 전용 속성이 필요할 때 상황에 직면했습니다 (실제로 도메인 속성이 변경되었는지 확인하기 위해 도메인 개체의 현재 상태를 데이터베이스에서로드하지 않음). 개체를 Modified로 설정하고 데이터베이스로 업데이트하면 중복 선택 및 병합 작업이 발생하지 않습니다.EF 4.1의 읽기 전용 속성

'false'값 설정이 지원되지 않으므로 DataContext.Entry(entity).Property(propertyName).IsModified = false;과 같이 쓸 수 없으며 예외가 발생합니다. (EF 4.1에서)

나는 저장소에서 읽기 전용 속성을 등록하기위한 간단한 구조를 만들었습니다. 따라서 읽기 전용 속성 만 쉽게 수정할 수 있습니다.

이 점에 대해 어떻게 생각하십니까?

public abstract class RepositoryBase<T> where T : class 
{ 
private const string MethodReferenceErrorFormat = "Expression '{0}' refers to a method, not a property."; 
private const string FieldReferenceErrorFormat = "Expression '{0}' refers to a field, not a property."; 

protected IList<PropertyInfo> _readOnlyProperties; 
     /// <summary> 
     /// This method is used to register readonly property for Entity. 
     /// </summary> 
     /// <param name="propertyLambda">Entity property as LambdaExpression</param> 
     protected void RegisterReadOnlyProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda) 
     { 
      Guard.ArgumentNotNull(propertyLambda, "propertyLambda"); 

      var propertyMember = propertyLambda.Body as MemberExpression; 
      if (propertyMember == null) 
      { 
       var exceptionMessage = string.Format(MethodReferenceErrorFormat, propertyLambda); 
       throw new ArgumentException(exceptionMessage); 
      } 

      var propertyInfo = propertyMember.Member as PropertyInfo; 
      if (propertyInfo == null) 
      { 
       var exceptionMessage = string.Format(FieldReferenceErrorFormat, propertyLambda); 
       throw new ArgumentException(exceptionMessage); 
      } 

      _readOnlyProperties.Add(propertyInfo); 
     } 

     /// <summary> 
     /// This method is used to attach domain object to DbContext and mark it as modified to save changes. 
     /// </summary> 
     /// <param name="entity">Detached entity</param> 
     public void SetModified(T entity) 
     { 
      Guard.ArgumentNotNull(entity, "entity"); 

      //Mark whole entity as Modified, when collection of readonly properties is empty. 
      if(_readOnlyProperties.Count == 0) 
      { 
       DataContext.Entry(entity).State = EntityState.Modified; 
       return; 
      } 

      //Attach entity to DbContext. 
      _dbSet.Attach(entity); 

      //Mark all properties except readonly as Modified. 
      var allProperties = entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 
      var propertiesForUpdate = allProperties.Except(_readOnlyProperties); 
      foreach (var propertyInfo in propertiesForUpdate) 
      { 
       DataContext.Entry(entity).Property(propertyInfo.Name).IsModified = true; 
      } 
     } 

답변

16

이렇게하면 작동하지만 수정 된 속성을 저장소에 직접 등록 할 필요가 없습니다. 등록 된 속성을 잊어 버릴 수 있으며 실수로 일부 변경 사항을 저장하지 않는 코드가 생깁니다. 복잡한 시나리오에서 저장소를 재사용 할 때 발견하기 어려운 버그가 될 것입니다. 저장소에서 Update와 같은 것을 호출 할 때마다 업데이트 된 속성에 대한 명시적인 정의를 좋아합니다. 또한 코드에 반영하는 것을 좋아하지 않습니다. 전체 응용 프로그램에 대해 각 엔터티에 대한 반사 된 데이터를 한 번만 가져 오도록 코드를 수정하지 않는 한 잘못 처리하는 경우가 있습니다.

은 내가 answer for EFv4를 썼다 있지만 쉽게 EFv4.1을 수정할 수 있습니다

public void Update(T entity, params Expression<Func<T, object>>[] properties) 
{ 
    _dbSet.Attach(entity); 
    DbEntityEntry<T> entry = _context.Entry(entity); 
    foreach (var selector in properties) 
    { 
     entry.Property(selector).IsModified = true; 
    } 
} 

당신은 그것을 좋아 호출합니다 :

repo.Update(entity, e => e.Name, e => e.Description); 
+0

감사합니다! 귀하의 버전이 좋아 보인다! – zonder

+0

이것을 사용하면 다음과 같은 오류가 발생합니다. 람다 식을 델리게이트 형식이 아니기 때문에 'Expression > []'형식으로 변환 할 수 없습니다 –

관련 문제