2012-03-06 9 views
6

मैं एक AuditLog एफई 4.1 का उपयोग कर लागू करने के लिए कोशिश कर रहा हूँ, SaveChanges (के रूप में निम्नलिखित स्थानों में चर्चा की अधिभावी) विधि द्वारा:इकाई की रूपरेखा DbContext SaveChanges() OriginalValue गलत

हालांकि मुझे "संशोधित" प्रविष्टियों में समस्याएं आ रही हैं। जब भी मैं प्रश्न में संपत्ति के OriginalValue पर पहुंचने का प्रयास करता हूं, तो यह हमेशा CurrentValue फ़ील्ड में समान मानता है।

मैं पहली बार इस कोड का उपयोग, और इसे सफलतापूर्वक प्रविष्टियां कि संशोधित कर रहे हैं की पहचान करता है:

public int SaveChanges(string userID) 
{ 

    // Have tried both with and without the following line, and received same results: 
    // ChangeTracker.DetectChanges(); 

    foreach (
     var ent in this.ChangeTracker 
        .Entries() 
        .Where(p => p.State == System.Data.EntityState.Added 
            p.State == System.Data.EntityState.Deleted    
            p.State == System.Data.EntityState.Modified)) 
    { 
     // For each change record, get the audit record entries and add them 
     foreach (AuditLog log in GetAuditRecordsForChange(ent, userID)) 
     { 
      this.AuditLog.Add(log); 
     } 

    } 

    return base.SaveChanges(); 
} 

समस्या यह (संक्षिप्त कोड) में है:

private List<AuditLog> GetAuditRecordsForChange(DbEntityEntry dbEntry, string userID) 
    { 
     if (dbEntry.State == System.Data.EntityState.Modified) 
     { 
      foreach (string propertyName in dbEntry.OriginalValues.PropertyNames) 
      { 
       if (!object.Equals(dbEntry.OriginalValues.GetValue<object>(propertyName), 
        dbEntry.CurrentValues.GetValue<object>(propertyName))) 
       { 
         // It never makes it into this if block, even when 
         // the property has been updated. 
       } 

       // If I updated the property "Name" which was originally "OldName" to the value "NewName" and then break here and inspect the values by calling: 
       //  ?dbEntry.OriginalValues.GetValue<object>("Name").ToString() 

       // the result will be "NewName" and not "OldName" as expected 
      } 
     } 
    } 

अजीब बात यह है कि है dbEntry.Property(propertyName).IsModified(); पर कॉल करें इस मामले में सच साबित होगा। यह सिर्फ इतना है कि OriginalValue में अपेक्षित मूल्य नहीं है। क्या कोई मुझे सही दिशा में इंगित करने में मदद करने के लिए तैयार होगा? मुझे यह सही तरीके से काम करने के लिए प्रतीत नहीं होता है।

+0

आप अपनी संस्थाओं से पूछताछ कैसे कर रहे हैं और फिर संपत्ति मूल्यों को बदल रहे हैं? यदि आप अनिवार्य रूप से इकाई को जोड़ रहे हैं और फिर राज्य को संशोधित करने के लिए सेट कर रहे हैं, तो मूल मान खो जाएंगे। मूल मानों को रखने के लिए आपको या तो ईएफ को क्वेरी से बचाने के लिए सभी तरह से इकाई को ट्रैक करने की आवश्यकता है, या आपको अपने कोड में मूल मानों का ट्रैक रखने की आवश्यकता है। –

+0

क्षमा करें - मैंने टिप्पणियों में कुछ कोड पोस्ट करने का प्रयास किया लेकिन यह अच्छी तरह से काम नहीं कर रहा था।मैं एक एमवीसी नियंत्रक की एक [HttpPost] कार्रवाई का उपयोग कर रहा हूँ। यह मेरे उत्पाद भंडार की "SaveProduct" विधि को कॉल करता है। भंडार में ऐसा लगता है कि मैं वास्तव में 'संदर्भ' कहता हूं। एंटर्री (उत्पाद) .State = EntityState.Modified' और फिर मैं संदर्भ पर SaveChanges। क्या आप मुझे उन संसाधनों को इंगित करने में सक्षम होंगे जो आपके द्वारा वर्णित दो तकनीकों का प्रदर्शन करते हैं? या कम से कम मुझे कुछ पॉइंटर्स दे? –

+0

मैं एमवीसी में _think_ ऐसा करने के लिए अनुशंसित तरीका छुपा क्षेत्रों के साथ होगा। अनिवार्य रूप से आप उन मूल मूल्यों को सहेज लेंगे जिन्हें आप छिपे हुए क्षेत्रों में रखते हैं और फिर बाद में उन्हें अपने पोस्ट में पढ़ते हैं। मैं इस के आसपास के सर्वोत्तम प्रथाओं को नहीं जानता या अगर मदद के लिए एक एमवीसी अबास्ट्रक्शन है। –

उत्तर

11

जब ईएफ डेटाबेस से किसी इकाई को पुनर्प्राप्त करता है तो वह उस इकाई के सभी गुणों के लिए मूल मानों का स्नैपशॉट लेता है। बाद में, जैसा कि इन गुणों के मूल्यों में परिवर्तन किए जाते हैं, वहीं मूल मूल्य वही रहेगा जबकि मौजूदा मान बदलते हैं।

हालांकि, ऐसा होने के लिए ईएफ को पूरे प्रक्रिया में इकाई को ट्रैक करने की आवश्यकता है। किसी वेब या अन्य एन-स्तरीय एप्लिकेशन में, आमतौर पर मान क्लाइंट को भेजे जाते हैं और इकाई से पूछताछ करने के लिए उपयोग किए गए संदर्भ का निपटारा किया जाता है। इसका मतलब है कि अब इकाई को ईएफ द्वारा ट्रैक नहीं किया जा रहा है। यह ठीक और अच्छा अभ्यास है।

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

+0

आपकी मदद के लिए फिर से धन्यवाद। मुझे यह उम्मीद है कि अब यह काम कर रहा है ... मुझे लगता है। सिर्फ स्पष्टीकरण के लिए: क्या आप कह रहे हैं कि कॉलिंग ** संदर्भ। एंटर्री (उत्पाद) .State = EntityState.Modified ** संदर्भ में 'उत्पाद' को दोबारा जोड़ता है और इसलिए यह इसके मूल मूल्यों का ट्रैक खो देता है? इसके अलावा, [यहां] (http://stackoverflow.com/questions/9591165/ef-4-how-to-properly-update-object-in-dbcontext-using-mvc-with-repository-patte) नई पोस्ट है मैंने अपने अनुवर्ती (केवल दूसरों के संदर्भ के लिए) के लिए बनाया है। –

+0

लेकिन परिवर्तन ट्रैकिंग उदाहरण में काम करने का तरीका @JoeDePung प्रश्न में क्यों जुड़ा हुआ है? – Jensen

13

यदि आप

dbEntry.OriginalValues.GetValue<object>(propertyName); 

को
dbEntry.GetDatabaseValues().GetValue<object>(propertyName); 

तो है कि काम करता है बदल जाते हैं।

+4

काम करता है, लेकिन ऑडिटिंग उद्देश्यों के लिए संभवतः बहुत महंगा है। – eoleary

+1

क्यों बहुत विस्तृत है? यदि आप परिवर्तन से पहले और बाद में मूल्य जानना चाहते हैं तो आपको डेटाबेस से पूछना होगा, कोई रास्ता नहीं। – sintetico82

+0

यह काम करता है .. लेकिन इसका कारण क्या है कि पहले व्यक्ति को मूल मूल्य नहीं है और क्यों वर्तमान @Uoleary के समान – Abi

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