2010-03-17 14 views
42

मैं किसी ऑब्जेक्ट संदर्भ में कई इकाइयां जोड़ रहा हूं।एक इकाई फ्रेमवर्क ऑब्जेक्ट संदर्भ को कैसे साफ़ करें?

try 
{ 
    forach (var document in documents) 
    { 
     this.Validate(document); // May throw a ValidationException. 

     this.objectContext.AddToDocuments(document); 
    } 

    this.objectContext.SaveChanges(); 
} 
catch 
{ 
    // How to clean-up the object context here? 

    throw; 
} 

तो दस्तावेजों के कुछ प्रमाणीकरण में सफल और एक विफल रहता है, सभी दस्तावेजों का सत्यापन पारित कर दिया वस्तु संदर्भ में जोड़ा रहते हैं। मुझे ऑब्जेक्ट संदर्भ को साफ़ करना होगा क्योंकि इसका पुन: उपयोग किया जा सकता है और निम्नलिखित हो सकता है।

var documentA = new Document { Id = 1, Data = "ValidData" }; 
var documentB = new Document { Id = 2, Data = "InvalidData" }; 
var documentC = new Document { Id = 3, Data = "ValidData" }; 

try 
{ 
    // Adding document B will cause a ValidationException but only 
    // after document A is added to the object context. 
    this.DocumentStore.AddDocuments(new[] { documentA, documentB, documentC }); 
} 
catch (ValidationException) 
{ 
} 

// Try again without the invalid document B. This causes an exception because 
// of a duplicate primary key - document A with id 1 is added a second time. 
this.DocumentStore.AddDocuments(new[] { documentA, documentC }); 

यह फिर से एक नकली प्राथमिक कुंजी की वजह से वस्तु संदर्भ के लिए और परिणाम SaveChanges() में दस्तावेज़ एक जोड़ने के लिए एक अपवाद फेंक देंगे।

इसलिए मुझे सत्यापन त्रुटि के मामले में पहले से ही जोड़े गए सभी दस्तावेज़ों को हटाना होगा। मैं निश्चित रूप से पहले सत्यापन कर सकता हूं और केवल सफलतापूर्वक सत्यापित होने के बाद ही सभी दस्तावेज जोड़ सकता हूं लेकिन दुख की बात यह पूरी समस्या को हल नहीं करती है - यदि SaveChanges() विफल रहता है, तो सभी दस्तावेज़ अभी भी जोड़े गए हैं लेकिन सहेजे गए हैं।

मैं द्वारा

this.objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added) 

सभी वस्तुओं लौटे अलग करने की कोशिश की लेकिन मैं एक अपवाद बताते हुए कि वस्तु संलग्न नहीं है हो रही है। तो मैं सभी अतिरिक्त लेकिन सहेजे गए ऑब्जेक्ट्स से कैसे छुटकारा पा सकता हूं?

+7

मैं एक ObjectContext पुन: उपयोग नहीं की सिफारिश करेंगे। ऐसे परिदृश्य हैं जहां यह समझ में आता है, लेकिन वे बहुत दुर्लभ हैं। अब याद रखें कि ऑब्जेक्ट कॉन्टेक्स्ट का उपयोग अधिक फुलाया जाता है, और यदि यह एक असंगत स्थिति में आता है (यानी कुछ आंशिक रूप से किया जाता है) तो आपको कुछ असंगत दुष्प्रभाव भी मिल सकते हैं। –

उत्तर

38

यह सिर्फ एक मामूली बग था लेकिन मैं यहां सवाल छोड़ने जा रहा हूं - शायद यह दूसरों की मदद करता है।

मैं निम्नलिखित

var objectStateEntries = this.objectContext 
          .ObjectStateManager 
          .GetObjectStateEntries(EntityState.Added); 

foreach (var objectStateEntry in objectStateEntries) 
{ 
    this.objectContext.Detach(objectStateEntry); 
} 

था, जबकि मैं निम्नलिखित

foreach (var objectStateEntry in objectStateEntries) 
{ 
    this.objectContext.Detach(objectStateEntry.Entity); 
} 

चाहता था और यह नहीं देख सकता था।

+7

एक तरफ के रूप में यह संभव है कि var objectStateEntries = this._context.ObjectStateManager .GetObjectStateEntries (EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged); सभी संलग्न वस्तुओं को अलग करने के लिए –

+0

इसे उत्तर के रूप में चिह्नित करें। –

+0

ध्यान दें कि कुछ मामलों में, 'objectStateEntry.Entity' शून्य हो जाएगा ('objectStateEntity' किसी इकाई के रिश्ते का वर्णन नहीं करता है), तो आपको शायद वहां एक शून्य जांच करनी चाहिए। –

1

पार्टी के लिए थोड़ा देर हो चुकी है लेकिन क्या आपने कार्य पैटर्न का यूनिट माना है?

संक्षेप में, यह आपका लेन-देन है जिसे आप रोलबैक सकता है (निपटान) है या (SaveChanges) के लिए प्रतिबद्ध करने की अनुमति होगी

एनबी: यह एक एसक्यूएल में के रूप में नहीं, एक ऑपरेशन में परिवर्तन के समूह में के रूप में लेन-देन है BEGIN ट्रैन SaveChanges() विधि द्वारा अभी भी आपके लिए यह सब कुछ संभाला गया है।

कुछ की तरह:

Public Class UnitOfWork 
    Implements IUnitOfWork 
    Implements IDisposable 
    Private ReadOnly Property ObjectContext As Interfaces.IObjectContext 

    Public Sub New(ByVal objectContext As Interfaces.IObjectContext) 
     _objectContext = objectContext 
    End Sub 

    Public Sub Dispose() Implements IDisposable.Dispose 
     If _objectContext IsNot Nothing Then 
      _objectContext.Dispose() 
     End If 
     GC.SuppressFinalize(Me) 
    End Sub 

    Public Sub Commit() Implements IUnitOfWork.Commit 
     _objectContext.SaveChanges() 
    End Sub 
End Class 

हर बार जब आप काम की एक इकाई बनाने के लिए, यह एक ObjectContext में लेता है - हम इन उत्पन्न करने के लिए इतना है कि एक नया बनाई गई है एकता उपयोग कर रहे हैं वर्ष से एक रहा है डिस्पोजेड

+2

काम की एक इकाई का उपयोग अभी भी संदर्भ से वस्तुओं को अलग नहीं करता है। यह सवाल का जवाब भी नहीं देता है। –

+0

@AgentShark पूरी तरह से निर्भर करता है कि आप अपनी 'रोलबैक' विधि को कैसे कार्यान्वित करते हैं। साथ ही, स्वीकृत उत्तर में सही कोड को डुप्लिकेट करने का कोई मतलब नहीं है जो स्पष्ट रूप से दिखाता है कि ऑब्जेक्ट्स को अलग करने के लिए – Basic

+0

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

36

डैनियल का जवाब मेरे लिए काम करता था, हालांकि एंटिटीफ्रेमवर्क एपीआई संस्करण 6+ में अलग है। यहाँ एक विधि मैं अपने कस्टम भंडार कंटेनर के लिए कहा कि DbContext के ChangeTracker से सभी संस्थाओं को अलग जाएगा:

/// <summary> 
    /// Detaches all of the DbEntityEntry objects that have been added to the ChangeTracker. 
    /// </summary> 
    public void DetachAll() { 

     foreach (DbEntityEntry dbEntityEntry in this.Context.ChangeTracker.Entries()) { 

      if (dbEntityEntry.Entity != null) { 
       dbEntityEntry.State = EntityState.Detached; 
      } 
     } 
    } 
+0

यह विधि मेरे लिए काम करती है :- धन्यवाद! – duardbr

0
var entries = ((DbContext)ef).ChangeTracker.Entries(); 
foreach (var entry in entries) 
{ 
    entry.State = System.Data.EntityState.Detached; 
} 
1

इकाई की रूपरेखा कोर 1.0 RC2 + का उपयोग करने वालों के लिए, मैं Garrys 'जवाब अपडेट किया गया।

संदर्भ

using Microsoft.EntityFrameworkCore; 
using Microsoft.EntityFrameworkCore.ChangeTracking; 

अपडेट किया गया कोड

 /// <summary> 
     /// Detaches all of the EntityEntry objects that have been added to the ChangeTracker. 
     /// </summary> 
     public void DetachAll() 
     { 
      foreach (EntityEntry entityEntry in this.Context.ChangeTracker.Entries().ToArray()) 
      { 
       if (entityEntry.Entity != null) 
       { 
        entityEntry.State = EntityState.Detached; 
       } 
      } 
     } 
संबंधित मुद्दे