5

में केवल पढ़ने योग्य गुणों को स्थिति में सामना करना पड़ता है जब मुझे 'आशावादी अद्यतन' के मामले में ईएफ रीडोनली प्रॉपर्टी की आवश्यकता होती है (आप डेटाबेस से अपने डोमेन ऑब्जेक्ट की वर्तमान स्थिति लोड नहीं करते हैं यह जांचने के लिए कि वास्तव में कौन से गुण बदले गए हैं। आपने बस अपनी ऑब्जेक्ट को संशोधित के रूप में सेट किया है और इसे डेटाबेस में अपडेट किया है। आप इस मामले में अनावश्यक चयन और मर्ज ऑपरेशन से बचें)।ईएफ 4.1

आप इस तरह कुछ नहीं लिख सकते: DataContext.Entry(entity).Property(propertyName).IsModified = false;, क्योंकि 'झूठी' मान की सेटिंग समर्थित नहीं है और आपको अपवाद मिलेगा। (ईएफ 4.1 में)

मैंने भंडार में रीडोनली गुणों को पंजीकृत करने के लिए एक सरल संरचना बनाई है। तो, आप आसानी से केवल nonreadonly गुणों को संशोधित कर सकते हैं।

आप इस बारे में क्या सोचते हैं?

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

यह काम करेगा लेकिन मुझे सीधे भंडार में संशोधित गुणों को पंजीकृत करने की आवश्यकता पसंद नहीं है। आप पंजीकृत गुणों के बारे में भूल सकते हैं और कोड दुर्घटनाग्रस्त कुछ परिवर्तनों को सहेज नहीं पाएगा - यह बग होगा जो जटिल परिदृश्यों में भंडार का पुन: उपयोग करते समय खोजना मुश्किल होगा। जब भी आप अपने भंडार पर अपडेट की तरह कुछ कहते हैं, तो मुझे अद्यतन गुणों की स्पष्ट परिभाषा पसंद है। इसके अलावा मुझे कोड में प्रतिबिंब पसंद नहीं है। जब तक आप पूरे कोड के लिए केवल एक बार प्रत्येक इकाई के बारे में प्रतिबिंबित डेटा प्राप्त करने के लिए अपना कोड संशोधित नहीं करते हैं, तो आप इसे गलत कर रहे हैं।

मैं 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

जब मैं इसका उपयोग करता हूं तो यह मुझे निम्न त्रुटि देता है, लैम्ब्डा अभिव्यक्ति को 'अभिव्यक्ति > []' टाइप करने के लिए परिवर्तित नहीं कर सकता क्योंकि यह एक प्रतिनिधि प्रकार नहीं है –

संबंधित मुद्दे