क्या यह जांचना संभव है कि क्या एंटिटी फ्रेमवर्क में कोई ऑब्जेक्ट पहले से ही डेटा संदर्भ से जुड़ा हुआ है?


86

जब किसी ऑब्जेक्ट को पहले से दिए गए संदर्भ से जोड़ा जाता है, तो मुझे संलग्न करने का प्रयास करते समय मुझे निम्न त्रुटि मिल रही है context.AttachTo(...):

समान कुंजी वाली कोई ऑब्जेक्ट पहले से ही ObjectStateManager में मौजूद है। ObjectStateManager एक ही कुंजी के साथ कई ऑब्जेक्ट्स को ट्रैक नहीं कर सकता है।

वहाँ की तर्ज पर कुछ हासिल करने का एक तरीका है:

context.IsAttachedTo(...)

चीयर्स!

संपादित करें:

जेसन उल्लिखित विस्तार विधि करीब है, लेकिन यह मेरी स्थिति के लिए काम नहीं करता है।

मैं किसी अन्य प्रश्न के उत्तर में उल्लिखित विधि का उपयोग करके कुछ काम करने की कोशिश कर रहा हूं:

पहले मैं * पंक्तियों को फिर से प्राप्त किए बिना * Linq से Entities * का उपयोग करके अपनी तालिका से एक या अधिक पंक्तियों को कैसे हटाऊं?

मेरा कोड कुछ इस तरह दिखता है:

var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();

यह ठीक काम करता है, सिवाय जब मैं उस उपयोगकर्ता के लिए कुछ और करता हूं जहां मैं उसी पद्धति का उपयोग करता हूं और एक डमी Userऑब्जेक्ट को संलग्न करने का प्रयास करता हूं । यह विफल रहता है क्योंकि मैंने पहले उस डमी उपयोगकर्ता ऑब्जेक्ट को संलग्न किया है। मैं इसके लिए कैसे जांच कर सकता हूं?

जवाबों:


57

यहाँ मैंने क्या किया, जो बहुत अच्छी तरह से काम करता है:

public static void AttachToOrGet<T>(this ObjectContext context, string entitySetName, ref T entity)
    where T : IEntityWithKey
{
    ObjectStateEntry entry;
    // Track whether we need to perform an attach
    bool attach = false;
    if (
        context.ObjectStateManager.TryGetObjectStateEntry
            (
                context.CreateEntityKey(entitySetName, entity),
                out entry
            )
        )
    {
        // Re-attach if necessary
        attach = entry.State == EntityState.Detached;
        // Get the discovered entity to the ref
        entity = (T)entry.Entity;
    }
    else
    {
        // Attach for the first time
        attach = true;
    }
    if (attach)
        context.AttachTo(entitySetName, entity);
}

आप इसे इस प्रकार कह सकते हैं:

User user = new User() { Id = 1 };
II.AttachToOrGet<Users>("Users", ref user);

यह बहुत अच्छी तरह से काम करता है क्योंकि यह ऐसा ही है जैसे context.AttachTo(...)आप हर बार ऊपर दिए गए आईडी ट्रिक का उपयोग कर सकते हैं। आप या तो पहले जुड़ी हुई वस्तु या अपनी खुद की वस्तु से जुड़े हुए हैं। CreateEntityKeyसंदर्भ पर कॉल करना सुनिश्चित करता है कि यह अच्छा और सामान्य है और आगे की कोडिंग के साथ समग्र कुंजियों के साथ भी काम करेगा (क्योंकि ईएफ पहले से ही हमारे लिए ऐसा कर सकता है!)।


मुझे एक समान समस्या हो रही थी, और यह सिर्फ मेरा हल किया - शानदार, चीयर्स! +1
RPM1984

4
जब स्ट्रिंग पैरामीटर उस संग्रह के लिए चयनकर्ता फ़ंक्शन द्वारा प्रतिस्थापित किया जाता है जो इकाई से संबंधित होता है तो और भी बेहतर होगा।
जैस्पर

1
किसी भी विचार क्यों (T)entry.Entityकभी-कभी अशक्त लौट आता है?
Tr1stan

1
मैं यह पता नहीं लगा सकता कि मुझे अपनी संस्था सेटसेटनेम में क्या स्थापित करना चाहिए। मुझे एक अपवाद मिलता रहता है। मैं वास्तव में निराश हूं क्योंकि मैं जो भी करना चाहता हूं वह एक उपयोगकर्ता को हटाना है जो मैं अपने आवेदन को उड़ाने वाले इतने गैर-छिपी भावना से निपटना नहीं चाहता हूं।
जूली

1
अगर Tपहले से ही है IEntityWithKey, तो आप entity.EntityKeyइसे फिर से संगठित करने या अनुमान लगाने / प्रदान करने की बजाय अपनी संपत्ति का उपयोग नहीं कर सकते EntitySetName?
ड्रेज़ॉस

54

एक सरल तरीका है:

 bool isDetached = context.Entry(user).State == EntityState.Detached;
 if (isDetached)
     context.Users.Attach(user);

1
यह मेरे लिए काम करता है, बस मुझे "डिटैक्ड" के बजाय "EntityState.Detached" का उपयोग करना था ...
Marcelo Myara

22
हम्म ने आपके समाधान की कोशिश की, लेकिन मेरे लिए यह पूरा सच है, लेकिन अभी भी वही त्रुटि है जब मैं संदर्भ के लिए प्रविष्टि संलग्न करने की कोशिश करता हूं
प्रोट्रूवर्स

बहुत बढ़िया। यहां तक ​​कि इसने मेरे जेनेरिक रिपोजिटरी के साथ काम किया।
ATHER

5
@Prokurors मैंने हाल ही में कारण सीखा कि मॉश का चेक हमेशा त्रुटि को रोकने के लिए पर्याप्त नहीं है, यह है कि .Include()'एड नेविगेशन गुणों को भी संलग्न करने का प्रयास किया जाता है जब आप कॉल करते हैं .Attachया इसे सेट EntityStateकरते हैं EntityState.Unchanged- और यदि कोई भी संस्थाओं को संदर्भित करता है तो वे संघर्ष करेंगे। एक ही इकाई। मैंने यह पता नहीं लगाया है कि केवल आधार इकाई को कैसे संलग्न किया जाए, इसलिए मुझे प्रत्येक "व्यवसाय लेनदेन" के लिए अलग संदर्भों का उपयोग करने के लिए परियोजना को थोड़ा नया स्वरूप देना होगा, जैसे कि इसके लिए डिज़ाइन किया गया था। मैं भविष्य की परियोजनाओं के लिए इस पर ध्यान दूंगा।
बीके

18

इस विस्तार विधि को आज़माएँ (यह अप्राप्त और ऑफ-कफ है):

public static bool IsAttachedTo(this ObjectContext context, object entity) {
    if(entity == null) {
        throw new ArgumentNullException("entity");
    }
    ObjectStateEntry entry;
    if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) {
        return (entry.State != EntityState.Detached);
    }
    return false;
}

आपके द्वारा संपादित की गई स्थिति को देखते हुए, आपको निम्न अधिभार का उपयोग करने की आवश्यकता हो सकती है जो EntityKeyकिसी वस्तु के बजाय स्वीकार करता है :

public static bool IsAttachedTo(this ObjectContext, EntityKey key) {
    if(key == null) {
        throw new ArgumentNullException("key");
    }
    ObjectStateEntry entry;
    if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) {
        return (entry.State != EntityState.Detached);
    }
    return false;
}

EntityKeyअपनी स्थिति में निर्माण करने के लिए , एक दिशानिर्देश के रूप में निम्नलिखित का उपयोग करें:

EntityKey key = new EntityKey("MyEntities.User", "Id", 1);

आप संपत्ति (इंटरफ़ेस से ) का उपयोग करके EntityKeyमौजूदा उदाहरण से प्राप्त कर सकते हैं ।UserUser.EntityKeyIEntityWithKey


यह बहुत अच्छा है, लेकिन यह मेरी स्थिति में मेरे लिए काम नहीं करता है ... मैं प्रश्न को विवरण के साथ अपडेट करूंगा। पी एस आप बूल बूलियन नहीं चाहते हैं, और स्थैतिक, लेकिन उस सुंदर भयानक विस्तार विधि के अलावा अन्य!
14

@joshcomley: मुझे लगता है कि आप TryGetObjectStateEntryएक के EntityKeyबजाय एक अधिभार का उपयोग कर संबोधित कर सकते हैं object। मैंने उसी के अनुसार संपादन किया है। मुझे बताएं कि क्या इससे कोई मदद नहीं मिलती है और हम ड्रॉइंग बोर्ड में वापस चले जाएंगे।
जेसन

आह बस यह देखा - मैं एक जवाब में उल्लिखित समाधान पर काम कर रहा था जो मैंने अभी पोस्ट किया है। आपकी मदद और संकेत के लिए +1 !!
15

किसी भी विचार क्यों मैं एक त्रुटि हो रही है, विवरण यहाँ है stackoverflow.com/questions/6653050/…
जोपर

6

उस ऑब्जेक्ट की इकाई कुंजी का उपयोग करना जिसे आप जांचना चाहते हैं:

var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey");
if (entry.State == EntityState.Detached)
{
  // Do Something
}

दयालुता,

सज्जन


0

यह सीधे ओपी प्रश्न का उत्तर नहीं देता है, लेकिन यह है कि मैंने कैसे हल किया।

यह उन लोगों के लिए है जो DbContextइसके बजाय उपयोग कर रहे हैं ObjectContext

    public TEntity Retrieve(object primaryKey)
    {
        return DbSet.Find(primaryKey);
    }

DbSet.Find विधि :

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

मूल रूप से, यह दिए गए संलग्‍न किए गए ऑब्जेक्ट को लौटाता है primaryKeyताकि आपको सही उदाहरण रखने के लिए लौटी हुई वस्तु पर बदलावों को लागू करना पड़े।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.