5

'İyimser güncelleme' durumunda EF readonly özelliği olması gerektiğinde durumla karşı karşıya kaldım (hangi özelliklerin gerçekten değiştirildiğini kontrol etmek için etki alanınızın mevcut durumunu veritabanından yüklemiyorsunuz). Nesnenizi yalnızca Değiştirilmiş olarak ayarlayın ve veritabanına güncelleyin. Bu durumda yedekli seçme ve birleştirme işlemlerini önleyebilirsiniz).Readonly özellikleri EF 4,1

Böyle bir şey yazamazsınız: DataContext.Entry(entity).Property(propertyName).IsModified = false;, çünkü 'yanlış' değeri ayarı desteklenmez ve bir istisna alırsınız. (EF 4.1)

Depodaki okuma özelliklerini kaydetmek için basit bir yapı oluşturdum. Yani, sadece nonreadonly özelliklerini değiştirebilirsin.

Bunun hakkında ne düşünüyorsunuz?

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

cevap

16

Bu işe yarar ancak değiştirilen özellikleri doğrudan depoda kaydetme gereğini sevmiyorum. Kayıtlı mülkleri unutabilirsiniz ve kod bazı değişiklikleri kaydetmeyecek şekilde yanlışlıkla kaydedilecektir - bu, karmaşık senaryolarda depoyu yeniden kullanırken karşılaşılması zor olan bir hata olacaktır. Deponuzda Güncelleme gibi bir şey aradığınızda güncellenen özelliklerin açık tanımını severim. Ayrıca kodda yansımayı sevmiyorum. Tüm uygulama için her bir varlık hakkında yalnızca bir kez yansıyan verileri almak için kodunuzu değiştirmedikçe, yanlış yaptığınızı kabul edersiniz.

Ben answer for EFv4 yazdım ancak kolayca EFv4.1 için değiştirilebilir:

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

Sen gibi arayacak:

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

Teşekkür! Sürümünüz iyi görünüyor! – zonder

+0

Bunu kullandığımda bana aşağıdaki hatayı verir, Lambda ifadesini 'İfade > []' olarak dönüştüremezsiniz, çünkü bu bir temsilci türü değil –