लेनदेन या SaveChanges (गलत) और AcceptAllChanges () का उपयोग करना?


346

मैं लेन-देन की जांच कर रहा हूं और ऐसा प्रतीत होता है कि जब तक मैं पास नहीं होता तब तक वे ईएफ में खुद का ख्याल falseरखते हैं SaveChanges()और AcceptAllChanges()अगर कोई कॉल नहीं है तो कॉल करें :

SaveChanges(false);
// ...
AcceptAllChanges();

अगर कुछ बुरा हो जाए तो क्या होगा? क्या मुझे रोलबैक नहीं करना है या, जैसे ही मेरी विधि कार्यक्षेत्र से बाहर हो जाती है, क्या लेनदेन समाप्त हो गया है?

किसी भी इंडेंटी कॉलम का क्या होता है जिसे लेनदेन के माध्यम से आधे तरीके से सौंपा गया था? मुझे लगता है कि अगर मेरा खराब होने से पहले किसी और ने मेरे साथ एक रिकॉर्ड जोड़ा तो इसका मतलब है कि एक लापता पहचान मूल्य होगा।

क्या TransactionScopeमेरे कोड में मानक वर्ग का उपयोग करने का कोई कारण है ?


1
इससे मुझे यह समझने में मदद मिली SaveChanges(fase); ... AcceptAllChanges();कि पहली जगह में एक पैटर्न क्यों था। ध्यान दें कि उपरोक्त प्रश्न का स्वीकृत उत्तर किसी ब्लॉग के लेखक द्वारा कैसे लिखा गया है - और वह ब्लॉग दूसरे प्रश्न में संदर्भित है। यह सब एक साथ आता है।
रेड मटर

जवाबों:


451

एंटिटी फ्रेमवर्क के साथ ज्यादातर समय SaveChanges()पर्याप्त होता है। यह एक लेनदेन बनाता है, या किसी भी परिवेश के लेनदेन में संलग्न करता है, और उस लेनदेन में सभी आवश्यक कार्य करता है।

कभी-कभी हालांकि SaveChanges(false) + AcceptAllChanges()युग्मन उपयोगी होता है।

इसके लिए सबसे उपयोगी स्थान उन स्थितियों में है जहां आप दो अलग-अलग संदर्भों में एक वितरित लेनदेन करना चाहते हैं।

यानी ऐसा कुछ (बुरा):

using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save and discard changes
    context1.SaveChanges();

    //Save and discard changes
    context2.SaveChanges();

    //if we get here things are looking good.
    scope.Complete();
}

यदि context1.SaveChanges()सफल हो context2.SaveChanges()जाता है, लेकिन विफल रहता है तो पूरा वितरित लेन-देन निरस्त कर दिया जाता है। लेकिन दुर्भाग्य से एंटिटी फ्रेमवर्क ने पहले ही बदलावों को छोड़ दिया है context1, इसलिए आप विफलता को फिर से खेलना या प्रभावी रूप से लॉग इन नहीं कर सकते।

लेकिन अगर आप अपना कोड इस तरह बदलते हैं:

using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save Changes but don't discard yet
    context1.SaveChanges(false);

    //Save Changes but don't discard yet
    context2.SaveChanges(false);

    //if we get here things are looking good.
    scope.Complete();
    context1.AcceptAllChanges();
    context2.AcceptAllChanges();

}

जबकि SaveChanges(false)डेटाबेस में आवश्यक कमांड भेजने के लिए कॉल किया जाता है, संदर्भ ही नहीं बदला जाता है, इसलिए यदि आवश्यक हो, तो आप इसे फिर से कर सकते हैं, या आप चाहें तो पूछताछ कर सकते ObjectStateManagerहैं।

इसका मतलब यह है कि यदि लेन-देन वास्तव में एक अपवाद फेंकता है जिसकी आप क्षतिपूर्ति कर सकते हैं, तो ObjectStateManagerकहीं न कहीं प्रत्येक संदर्भ की पुन: कोशिश या लॉगिंग स्थिति ।

अधिक के लिए मेरी ब्लॉग पोस्ट देखें ।


3
यह बहुत अच्छा है, धन्यवाद ... तो अगर कुछ विफल नहीं है तो मुझे रोलबैक करना होगा ?? SaveChanges, इसे सहेजे जाने के लिए चिह्नित करता है, लेकिन वास्तव में जब तक मैं स्वीकार नहीं करता है तब तक यह प्रतिबद्ध नहीं है .. लेकिन अगर कुछ गलत हो जाता है .. तो मुझे रोलबैक करने की आवश्यकता होगी, ताकि मेरी वस्तु अपनी सही स्थिति में वापस आ जाए?
निशान

33
@ मर्क: यदि आप "रोल-बैक" से मतलब रखते हैं, तो अपनी वस्तुओं को उस स्थिति में वापस लाएं, जो वे डेटाबेस में हैं, तो नहीं, आप ऐसा नहीं करना चाहेंगे, क्योंकि आप उपयोगकर्ता के सभी परिवर्तन वस्तुओं में खो देंगे। । SaveChanges(false)डेटाबेस के लिए वास्तविक अद्यतन करता है, जबकि AcceptAllChanges()EF को बताता है, "ठीक है, आप भूल सकते हैं कि किन चीज़ों को सहेजने की आवश्यकता है, क्योंकि उन्हें सफलतापूर्वक बचा लिया गया है।" यदि SaveChanges(false)विफल रहता है, AcceptAllChanges()तो कभी भी कॉल नहीं किया जाएगा और EF आपकी ऑब्जेक्ट को उन गुणों के रूप में मानेगा, जिन्हें परिवर्तित किया गया था और उन्हें डेटाबेस में वापस सहेजने की आवश्यकता है।
ब्लूराजा - डैनी पफ्लुगुएट

क्या आप सलाह दे सकते हैं कि कोड पहले का उपयोग करके यह कैसे करें? SaveChanges या AcceptAllChanges विधि का कोई पैरामीटर नहीं है
कर्स्टन लालच

2
मैंने इस तकनीक को कोड फर्स्ट के साथ उपयोग करने के बारे में एक प्रश्न पूछा है
कर्स्टन लालच

13
यह अब EF 6.1 में संभव नहीं है। क्या आप जानते हैं कि अब काम करने के लिए किस तरह के समायोजन की जरूरत है?
एलेक्स ड्रेस्को जू

113

यदि आप EF6 (Entity Framework 6+) का उपयोग कर रहे हैं, तो यह डेटाबेस कॉल के लिए SQL में बदल गया है।
देखें: http://msdn.microsoft.com/en-us/data/dn456843.aspx

संदर्भ का उपयोग करें। Database.BeginTransaction।

MSDN से:

using (var context = new BloggingContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
        try 
        { 
            context.Database.ExecuteSqlCommand( 
                @"UPDATE Blogs SET Rating = 5" + 
                    " WHERE Name LIKE '%Entity Framework%'" 
                ); 

            var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
            foreach (var post in query) 
            { 
                post.Title += "[Cool Blog]"; 
            } 

            context.SaveChanges(); 

            dbContextTransaction.Commit(); 
        } 
        catch (Exception) 
        { 
            dbContextTransaction.Rollback(); //Required according to MSDN article 
            throw; //Not in MSDN article, but recommended so the exception still bubbles up
        } 
    } 
} 

52
जब आप लेन-देन पर "उपयोग" कर रहे हों तो रॉलबैक के साथ ट्राइ-कैच की आवश्यकता नहीं होती है।
राबर्ट

12
मैं इस तरह के अपवाद को फंसाने के लिए एक अपवाद ले रहा हूं। यह डेटाबेस ऑपरेशन को चुपचाप विफल करने का कारण बनता है। SO की प्रकृति के कारण, कोई व्यक्ति इसका उदाहरण ले सकता है और इसका उपयोग उत्पादन एप्लिकेशन में कर सकता है।
B2K

3
@ B2K: अच्छी बात है, लेकिन यह कोड लिंक किए गए Microsoft लेख से कॉपी किया गया है । मुझे आशा है कि कोई भी उत्पादन में अपने कोड का उपयोग नहीं करता है :)
जे ब्रायन मूल्य

6
@Robert MSDN लेख के अनुसार रोलबैक () आवश्यक है। वे जानबूझकर TransactionScope उदाहरण के लिए रोलबैक कमांड को छोड़ देते हैं। @ B2K मैंने throw;MSDN स्निपेट में जोड़ा है और स्पष्ट रूप से इंगित किया है कि यह MSDN लेख से मूल नहीं है।
टोड

6
(यदि सही है) तो यह स्पष्ट हो सकता है: EF + MSSQL जैसी ध्वनियों को रोलबैक की आवश्यकता नहीं है, लेकिन EF + अन्य SQL प्रदाता हो सकते हैं। चूंकि EF को माना जाता है कि वह किस डेटाबेस से बात कर रहा है, Rollback()जिसे MySql से बात करने या उस स्वचालित व्यवहार के बारे में कुछ नहीं कहा जाता है।
शब्द जेरेड

-5

क्योंकि कुछ डेटाबेस dbContextTransaction.Commit () पर एक अपवाद फेंक सकते हैं, इसलिए यह बेहतर है:

using (var context = new BloggingContext()) 
{ 
  using (var dbContextTransaction = context.Database.BeginTransaction()) 
  { 
    try 
    { 
      context.Database.ExecuteSqlCommand( 
          @"UPDATE Blogs SET Rating = 5" + 
              " WHERE Name LIKE '%Entity Framework%'" 
          ); 

      var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
      foreach (var post in query) 
      { 
          post.Title += "[Cool Blog]"; 
      } 

      context.SaveChanges(false); 

      dbContextTransaction.Commit(); 

      context.AcceptAllChanges();
    } 
    catch (Exception) 
    { 
      dbContextTransaction.Rollback(); 
    } 
  } 
} 

7
मैं इस तरह के अपवाद को फंसाने के लिए एक अपवाद ले रहा हूं। यह डेटाबेस ऑपरेशन को चुपचाप विफल करने का कारण बनता है। SO की प्रकृति के कारण, कोई व्यक्ति इसका उदाहरण ले सकता है और इसका उपयोग उत्पादन एप्लिकेशन में कर सकता है।
B2K

6
क्या यह अनिवार्य रूप से इस अन्य उत्तर के समान नहीं है जो MSDN पृष्ठ को उद्धरण देता है? एकमात्र अंतर जो मैं देख रहा हूं, वह यह है कि आप पास falseहोते हैं context.SaveChanges();, और इसके अलावा कॉल करते हैं context.AcceptAllChanges();
वाई हा ली

@ बी 2 के रोलबैक की आवश्यकता नहीं है - अगर लेन-देन काम नहीं करता है तो कुछ भी प्रतिबद्ध नहीं है। रोलबैक में स्पष्ट कॉल भी विफल हो सकती है - मेरा जवाब यहां देखें stackoverflow.com/questions/41385740/…
Ken

रोलबैक वह नहीं है जिस पर मुझे आपत्ति है। इस जवाब के लेखक ने अपवाद को फिर से उखाड़ फेंकने के लिए अपने कोड को अपडेट किया, इस प्रकार यह हल करना कि मैं क्या आपत्ति कर रहा था।
B2K

क्षमा करें, मैंने अपने फोन से टिप्पणी की। टोड ने अपवाद को फिर से फेंका, eMeL नहीं। पकड़ में कुछ ऐसा होना चाहिए जो डेवलपर या रोलबैक के कारण किसी समस्या के उपयोगकर्ता को सूचित करता है। यह लॉग फ़ाइल में लिखा जा सकता है, अपवाद को फिर से पढ़ना या उपयोगकर्ता को एक संदेश वापस करना।
बी 2 के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.