2012-05-10 16 views
8

मैं आरआईए सेवाओं के साथ काम कर रहा था जहां ऑब्जेक्टकॉन्टेक्स्ट में RejectChanges() विधि है। हालांकि, अब मैं डेस्कटॉप एप्लिकेशन में ईएफ 4.4 के साथ काम कर रहा हूं और मुझे वह विधि नहीं मिल रही है। तो, मेरा सवाल है: एक दृश्य में जहां मैं उपयोगकर्ता को संग्रह पर बैच क्रूड ऑपरेशन करने की अनुमति देता हूं, मैं सभी परिवर्तनों को कैसे वापस लाऊंगा? मैं संदर्भ को दोबारा बनाने और डेटा को दोबारा लाने के साथ जा सकता था, लेकिन अगर मुझे 1-2 इकाइयों में परिवर्तन वापस करने की ज़रूरत है तो वह बहुत अनावश्यक है।डीबीकॉन्टेक्स्ट और अस्वीकृतिChanges

तो, परिवर्तनों को अस्वीकार करने का सबसे अच्छा तरीका क्या है? और, हम कैसे जानते हैं कि संदर्भ कुछ कर रहा है (IsBusy)?

उत्तर

11

ईएफ में कोई प्रत्यक्ष "अस्वीकार परिवर्तन" ऑपरेशन नहीं है। आप ChangeTracker/ObjectStateManager में इकाई प्रविष्टियों के माध्यम से जा सकते हैं और संशोधित इकाइयों के लिए मूल मानों के साथ वर्तमान मानों को ओवरराइट कर सकते हैं। आप अतिरिक्त इकाइयों को भी अलग कर सकते हैं और हटाए गए इकाइयों को अपरिवर्तित में बदल सकते हैं, लेकिन यह सब केवल तभी काम करेगा यदि आप (या ईएफ आंतरिक रूप से) किसी भी स्वतंत्र संघ (संबंध) की स्थिति को नहीं बदलते हैं। यदि आप संबंधों के साथ भी काम करते हैं तो पूरी चीज अधिक जटिल हो सकती है क्योंकि आपको रिश्तों को भी वापस करना होगा - ऐसे मामले में डेटा को फिर से लोड करना आसान है।

DbContext एपीआई में परिवर्तनों को वापस तो आप इस कोशिश कर सकते हैं के लिए:

foreach (var entry in context.ChangeTracker 
          .Entries<YourEntityType>() 
          .Where(e => e.State == EntityState.Modified)) 
{ 
    entry.CurrentValues.SetValues(entry.OriginalValues); 
} 

मुझे लगता है कि मुख्य समस्या यह है जिस तरह से कैसे आप संस्थाओं के साथ काम है इस मामले में - आप लाइव डेटा पर परिवर्तन की अनुमति और एफई अपने तर्क करता है परिवर्तन किए जाने पर डेटा को लगातार बनाए रखने के लिए, लेकिन बाद में आप तय करते हैं कि वे परिवर्तन सहेजे नहीं जाएंगे। इस मामले में आप निम्न में से एक करना चाहिए:

  • त्यागें बदल डेटा और संपूर्ण डेटा सेट को फिर से लोड (संदर्भ की पुनर्रचना के द्वारा)
  • अलग इस तर्क को लाइव डेटा पर काम नहीं करने के लिए और एफई संदर्भ केवल करने के लिए डेटा संशोधन धक्का जब संशोधन वास्तव में पुष्टि की जाती है

संदर्भ कुछ ऐसा करने के लिए कहता है तो संदर्भ कुछ कर रहा है। यह कभी भी व्यस्त नहीं होता है।

+0

संदर्भ को पुनर्निर्मित करना एक अच्छा समाधान होगा। हालांकि, मुझे संबंधित डेटा सिंक्रनाइज़ करने में समस्याएं आ रही थीं। एक उदाहरण यह होगा कि मेरे पास व्यूए पर कलेक्शनए पर सीआरयूडी था, और सीआरयूडी को सीओएलबी पर बीएल पर सीएलयूडी था। कलेक्शनबी में संग्रह ए के संदर्भ भी हैं। इसलिए, अगर मेरे पास कलेक्शनए और कलेक्शन बी दोनों के लिए 2 संदर्भ ऑब्जेक्ट हैं, तो मैं व्यूए पर कलेक्शनए को बदलता हूं, तो मैं व्यूबी को कैसे सिंक करूं? एक संदर्भ होने पर सब कुछ सिंक हो जाता है, क्योंकि हम वास्तव में केवल एक उदाहरण संग्रह ए पर काम कर रहे हैं, दो नहीं। "वैश्विक" संदर्भ को दोबारा बनाने से एक गड़बड़ी पैदा होगी। :) क्या मैंने "वैश्विक" संदर्भ का उपयोग करके गलती की? – Goran

+0

"व्यस्त" के लिए, मुझे चिंता थी कि अगर मैं एसिंक मैनेर में लोड जारी करता हूं तो क्या होगा, और फिर मैं एक और लोड जारी करने का प्रयास करता हूं, जबकि पहले खत्म नहीं हुआ था? इस तरह से मैं जांच सकता हूं कि यह "व्यस्त" है, इसलिए मैं एक नया लोड कतार कर सकता था। – Goran

+0

+1 यह देखने के लिए कि ज्यादातर लोग क्या याद करते हैं। संबंध: उन परिवर्तनों को ट्रैक करना संभव है जिन्हें राज्य के लिए प्रविष्टि संग्रह को देखकर उठाया नहीं जाएगा! = अपरिवर्तित। (ईएफ v6।) – mwardm

1

यह मेरे लिए काम करता है:

public void RejectChanges() { 
    var context = ((IObjectContextAdapter)this).ObjectContext; 
    foreach (var change in this.ChangeTracker.Entries()) { 
     if (change.State == EntityState.Modified) { 
      context.Refresh(RefreshMode.StoreWins, change.Entity); 
     } 
     if (change.State == EntityState.Added) { 
      context.Detach(change.Entity); 
     } 
    } 
} 

इस = इस मामले

+1

हटाए गए इकाइयों के बारे में क्या? साथ ही, आप उन उपयोगकर्ताओं के लिए नया डेटा कैसे प्राप्त करेंगे जो अन्य उपयोगकर्ताओं द्वारा बदले गए हैं, है ना? – Goran

2

में DbContext मैं जानता हूँ कि यह एक पुराने सवाल है। हालांकि, कोई भी जवाब मेरी स्थिति में फिट नहीं है। मुझे संग्रह में केवल 1 इकाई पर हुए परिवर्तनों को अस्वीकार करने की आवश्यकता थी। यह वही मेरे लिए काम किया है:

var objectContext = (myDbContext as IObjectContextAdapter).ObjectContext; 
    objectContext.Refresh(RefreshMode.StoreWins, partMaster); 
+0

हालांकि सवाल संग्रह परिवर्तनों के बारे में था, एक इकाई नहीं, मुझे नहीं पता कि किसी भी उत्तर ने आपकी मदद कैसे की? आपके ऊपर दिए गए उत्तर (TheSoul75) बिल्कुल वही हैं जैसा आप सुझाव हैं, केवल यह संग्रह में सभी वस्तुओं के लिए करता है। – Goran

+0

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

+1

ठीक है, आप foreach का उपयोग नहीं करते हैं, लेकिन आप अनिवार्य रूप से एक ही तकनीक (स्टोरविंस के साथ ताज़ा करें) का उपयोग कर रहे हैं, इसलिए मुझे आपके उत्तर में जोड़ा गया मूल्य नहीं दिखाई देता है, क्योंकि आपने अभी लूप को हटा दिया है। – Goran

11
public void RejectChanges() 
     { 
      foreach (var entry in ChangeTracker.Entries()) 
      { 
       switch (entry.State) 
       { 
        case EntityState.Modified: 
         { 
          entry.CurrentValues.SetValues(entry.OriginalValues); 
          entry.State = EntityState.Unchanged; 
          break; 
         } 
        case EntityState.Deleted: 
         { 
          entry.State = EntityState.Unchanged; 
          break; 
         } 
        case EntityState.Added: 
         { 
          entry.State = EntityState.Detached; 
          break; 
         } 
       } 
      } 
     } 
+0

ऐसा एकमात्र ऐसा उत्तर लगता है जो डेटाबेस को मारने के बिना सभी राज्यों को संभालता है। +1 – Dan

+0

क्या होगा अगर मैंने केवल संदर्भ बदल दिए? विशेष रूप से शुद्ध एम: एन जब कोई विदेशी कुंजी संपत्ति प्रभावित नहीं होती है? – springy76

0

यह .... एक पुराने जवाब लेकिन किसी भी नए आगंतुकों के लिए उपयोगी हो सकता है पुनः लोड समारोह डेटा स्रोत से वस्तु को फिर से लोड और किसी भी मौजूदा परिवर्तन ओवरराइट हो जाएँगे और नई लोड की गई इकाई में अपरिवर्तित स्थिति होगी।

public static void UndoEntityChanges(object Entity) 
{ 
    <EFModelContainer>.Entry(Entity).Reload(); 
} 
संबंधित मुद्दे