2012-10-13 16 views
19

के साथ इकाई फ्रेमवर्क सत्यापन मैं डीबीकॉन्टेक्स्ट और पीओसीओ इकाइयों के साथ इकाई फ्रेमवर्क 5.0 का उपयोग कर रहा हूं। वहाँ एक साधारण 3 गुण युक्त इकाई है:आंशिक अद्यतन

public class Record 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public bool IsActive { get; set; } 
} 

शीर्षक फ़ील्ड हमेशा असंशोधित है, और यूआई बस इसे संशोधित करने के लिए किसी भी इनपुट बॉक्स प्रदान किए बिना यह प्रदर्शित करता है। यही कारण है कि Title फ़ील्ड को सर्वर पर भेजा जाने पर null पर सेट किया गया है।

public class EFRepository<TEntity> 
{ 
    ... 
    public void PartialUpdate(TEntity entity, params Expression<Func<TEntity, object>>[] propsToUpdate) 
    { 
     dbSet.Attach(entity); 
     var entry = _dbContext.Entry(entity); 
     foreach(var prop in propsToUpdate) 
      contextEntry.Property(prop).IsModified = true; 
    } 
} 

और कॉल:

यहाँ कैसे मैं एफई बता इकाई का आंशिक अद्यतन (केवल IsActive क्षेत्र) करने के लिए यहां

repository.PartialUpdate(updatedRecord, r => r.IsActive); 

कॉलिंग SaveChanges विधि, मैं DbEntityValidationException मिलता है, कि मुझे बताता है, Title आवश्यक है। जब मैं dbContext.Configuration.ValidateOnSaveEnabled = false सेट करता हूं, तो सब कुछ ठीक है। क्या पूरे संदर्भ पर सत्यापन अक्षम करने से बचने के लिए कोई तरीका है और ईएफ को उन गुणों को मान्य करने के लिए नहीं बताया गया है जिन्हें अद्यतन नहीं किया जा रहा है? अग्रिम धन्यवाद।

+1

इस काम का एक बहुत कुछ है जो काफी अन्यथा से निपटने के लिए आसान है करने के लिए की तरह लगता है। आप केवल अपने पढ़ने-योग्य मॉडल आइटम के साथ फ़ॉर्म पर एक छिपे हुए फ़ील्ड को शामिल करते हैं, फिर उन्हें अपडेट में शामिल किया जाता है और ईएफ इसकी परिवर्तन ट्रैकिंग करता है और जानता है कि मान नहीं बदला है। –

+2

स्टब इकाइयों के बारे में क्या? उदाहरण के लिए, मेरे पास एक एक्शन विधि है जो हटाए गए इकाई को चिह्नित करती है। निम्नलिखित कोड: 'var व्यक्ति = नया व्यक्ति {आईडी = 5}; dbSet.Attach (व्यक्ति); dbSet.Entry (व्यक्ति)। प्रॉपर्टी (पी => पी। आईएस हटाया गया) IsModified = true; dbContext.SaveChanges(); 'एक ही अपवाद का कारण बन जाएगा। क्या डीबी कॉन्टेक्स्ट सत्यापन स्टब इकाइयों के साथ अच्छी तरह से काम करता है? मैं डेटाबेस से पूरी इकाई को हटाए जाने के लिए बस इसे चिह्नित करने के लिए अधिग्रहण करना चाहता हूं। – Skog

+0

क्या यह वास्तव में काम करता है? अटैच का उपयोग तब किया जाता है जब आपके पास हाथ में एक इकाई होती है और आप सुनिश्चित हैं कि यह इकाई डेटाबेस में मौजूद है और समान है। आप एक ऐसी इकाई संलग्न करते हैं जो स्टोर में से अलग है (शीर्षक अलग है)। फिर आप इकाई को संशोधित के रूप में चिह्नित करते हैं (किसी संपत्ति को संशोधित करने के लिए चिह्नित करके)। चूंकि ईएफ इकाइयों पर काम करता है और गुणों पर नहीं, यह सभी गुणों को अपडेट करेगा और न केवल संशोधित के रूप में चिह्नित किया जाएगा। ईएफ का मेरा मानसिक मॉडल मुझे बताता है कि डेटाबेस में शीर्षक कॉलम इसके बाद शून्य हो जाएगा। क्या आप जांच सकते हैं कि यह मामला नहीं है? – Pawel

उत्तर

19

यदि आप आंशिक अपडेट या स्टब इकाइयों का उपयोग करते हैं (दोनों दृष्टिकोण बहुत मान्य हैं!) आप वैश्विक ईएफ सत्यापन का उपयोग नहीं कर सकते क्योंकि it doesn't respect your partial changes - यह हमेशा पूरी इकाई को मान्य करता है। डिफ़ॉल्ट सत्यापन तर्क के साथ आपको उल्लिखित कॉलिंग से इसे बंद करना होगा:

dbContext.Configuration.ValidateOnSaveEnabled = false 

और प्रत्येक अद्यतन संपत्ति को अलग से मान्य करें। यह उम्मीद है कि जादू क्या करना चाहिए लेकिन मैं यह कोशिश नहीं की क्योंकि मैं बिल्कुल एफई सत्यापन का उपयोग नहीं करते:

foreach(var prop in propsToUpdate) { 
    var errors = contextEntry.Property(prop).GetValidationErrors(); 
    if (erros.Count == 0) { 
     contextEntry.Property(prop).IsModified = true; 
    } else { 
     ... 
    } 
} 

आप कदम आगे जाना चाहते हैं तो आप अपने संदर्भ में ValidateEntity अधिरोहण करने का प्रयास कर सकते हैं और में मान्यता reimplement जिस तरह से यह इकाई की स्थिति और IsModified गुणों की स्थिति के आधार पर पूरी इकाई या केवल चयनित गुणों को मान्य करता है - जो आपको आंशिक अपडेट और स्टब इकाइयों के साथ ईएफ सत्यापन का उपयोग करने की अनुमति देगा।

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

बातें मैं अपने बहुत लंबे बैकलॉग में से एक जांच करने के लिए कैसे मान्यता SaveChanges आपरेशन की गति को प्रभावित करता है - मैं EF4 (पूर्व EF4.1 करने के लिए) में अपने ही मान्यता एपीआई DataAnnotations के आधार पर और उनके Validator वर्ग किया करते थे और मैंने बहुत खराब प्रदर्शन के कारण इसे जल्द ही बंद कर दिया।

देशी एसक्यूएल का उपयोग करने के साथ वर्कअराउंड स्टब इकाइयों या बंद सत्यापन के साथ आंशिक अपडेट का उपयोग करने के समान प्रभाव है = आपकी संस्थाएं अभी भी मान्य नहीं हैं लेकिन इसके अतिरिक्त आपके परिवर्तन काम की एक इकाई का हिस्सा नहीं हैं।

+0

जब भी आप इकाई सत्यापन अक्षम करते हैं तो सब ठीक नहीं है। उदाहरण के लिए मेरे पास गुण हैं जिनके पास अपरिवर्तित मूल्य होगा लेकिन जब मैं एक स्पष्ट मूल्य निर्धारित नहीं करता हूं तो इन प्रोप को पूर्णांक के लिए 0 जैसे सभी पूर्ण रूप से डिफ़ॉल्ट मान मिलते हैं। नतीजा यह है कि इसे वास्तव में काम करना है, आपको रॉ एसक्यूएल का उपयोग करना है, इस परिदृश्य के लिए ईएफ 6 द्वारा कोई कामकाज या समाधान नहीं है।x – Pascal

+1

@ पास्कल: यदि उनके पास अपरिवर्तित मान है तो आपको या तो उस मान को भरना चाहिए (इसलिए डिफ़ॉल्ट मान का उपयोग नहीं किया जाएगा) या आपको आंशिक अपडेट का उपयोग करना चाहिए और डेटाबेस के अपडेट में उन्हें पास नहीं करना चाहिए। –

+0

विकल्प 1: मैं उस मान को भरना नहीं चाहता क्योंकि मुझे अपडेट करने के लिए प्रत्येक इकाई के लिए डेटाबेस में फिर से जाना होगा विकल्प 2: मुझे समझ में नहीं आता कि आप थोड़ा कोड कृपया दिखा सकते हैं? या अधिक स्पष्टीकरण? मैंने संपत्ति के साथ आंशिक अद्यतन का उपयोग किया। IModified = true; यहाँ और क्या गुम है? – Pascal

15

Ladislav's answer के संदर्भ में, मैंने इसे DbContext कक्षा में जोड़ा है, और अब यह उन सभी गुणों को हटा देता है जो संशोधित नहीं हैं।
मुझे पता है कि यह उन गुणों के लिए सत्यापन को पूरी तरह से छोड़ नहीं रहा है बल्कि इसे छोड़कर, लेकिन ईएफ प्रति इकाई को मान्य नहीं करता है, और पूरी सत्यापन प्रक्रिया को फिर से लिखना मेरे लिए बहुत परेशानी थी।

protected override DbEntityValidationResult ValidateEntity(
    DbEntityEntry entityEntry, 
    IDictionary<object, object> items) 
{ 
    var result = base.ValidateEntity(entityEntry, items); 
    var falseErrors = result.ValidationErrors 
    .Where(error => 
    { 
     if (entityEntry.State != EntityState.Modified) return false; 
     var member = entityEntry.Member(error.PropertyName); 
     var property = member as DbPropertyEntry; 
     if (property != null) 
     return !property.IsModified; 
     else 
     return false;//not false err; 
    }); 

    foreach (var error in falseErrors.ToArray()) 
    result.ValidationErrors.Remove(error); 
    return result; 
} 
+1

धन्यवाद! यह मुझे मिला सबसे शानदार तरीका है, लेकिन मैं इस शर्त को जोड़ने के लिए भी सुझाव दूंगा 'अगर (entityEntry.State! = EntityState.Modified) झूठी वापसी;' 'कहां 'के अंदर, झूठी त्रुटियों को हटाने के लिए केवल सुनिश्चित करने के लिए इकाई, अन्यथा सत्यापन जोड़ने के दौरान सभी हटा दिए जाएंगे, सिर्फ इसलिए कि ध्वज 'IsModified' सेट नहीं है। –

+0

मैंने माइकल डेनी के व्यवहार को रोकने के लिए 'var (entityEntry.State == EntityState.Modified) '' var falseErrors' को लपेटकर 'foreach'' को जोड़ा है। लिंक की क्वेरी में ऐसा करने से बेहतर है। –

+0

अरे शिमी, इस स्निपेट के लिए चीयर्स। आश्चर्य है कि अगर आपको पता है कि यह अभी भी EF6.1 पर आवश्यक है? मेरे पास अभी एक चेक था, और ईएफ 6 2013 तक बाहर था, लेकिन ऐसा लगता है कि पिछले अप्रैल से ईएफ पक्ष में सुधार हुआ है? – Jono

1

यह पिछले @Shimmy प्रतिक्रिया का एक रीमिक्स है और यह एक संस्करण है जिसका मैं वर्तमान में उपयोग करता हूं।

मैं क्या जोड़ दिया है खंड (entityEntry.State != EntityState.Modified) return false;Where में है:

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items) 
{ 
    var result = base.ValidateEntity(entityEntry, items); 

    var falseErrors = result 
     .ValidationErrors 
     .Where(error => 
     { 
      if (entityEntry.State != EntityState.Modified) return false; 
      var member = entityEntry.Member(error.PropertyName); 
      var property = member as DbPropertyEntry; 
      if (property != null) return !property.IsModified; 
      return false; 
     }); 

    foreach (var error in falseErrors.ToArray()) 
    { 
     result.ValidationErrors.Remove(error); 
    } 

    return result; 
} 
संबंधित मुद्दे