5

मैं एंटिटी फ्रेमवर्क कोड के साथ किसी समस्या में भाग रहा हूं-पहले एमवीसी 3 में। मैं इस अपवाद को मार रहा हूं:इकाई फ्रेमवर्क कोड-प्रथम: "ऑब्जेक्टस्टेट प्रबंधक एक ही कुंजी के साथ एकाधिक ऑब्जेक्ट्स को ट्रैक नहीं कर सकता है।"

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

यह एसओ पर कई बार संबोधित किया गया है, लेकिन मुझे अपनी स्थिति में सुझाए गए समाधानों में से किसी एक का उपयोग करने में परेशानी हो रही है।

FestORM.SaleMethod method = new FestORM.SaleMethod 
{ 
    Id = 2, 
    Name = "Test Sale Method" 
}; 
FestContext context = new FestContext(); 

//everything works without this line: 
string thisQueryWillMessThingsUp = 
    context.SaleMethods.Where(m => m.Id == 2).Single().Name; 

context.Entry(method).State = System.Data.EntityState.Modified; 
context.SaveChanges(); 

संपादित स्पष्ट करने के लिए: मैं एक उद्देश्य यह है कि पहले से ही डेटाबेस में मौजूद है अद्यतन करने के लिए प्रयास कर रहा हूँ

यहाँ एक कोड नमूना है।

सब कुछ कोड में उल्लिखित क्वेरी के बिना ठीक काम करता है। मेरे आवेदन में, मेरा नियंत्रक संदर्भ को तत्काल कर रहा है, और यह संदर्भ कई रिपॉजिटरीज़ को पास किया जाता है जो नियंत्रक द्वारा उपयोग किए जाते हैं - इसलिए मैं प्रारंभिक क्वेरी ऑपरेशन के लिए बस एक अलग संदर्भ का उपयोग करने में सक्षम नहीं हूं। मैंने ऑब्जेक्टस्टेट मैनेजर में ट्रैक होने से इकाई को निकालने का प्रयास किया है, लेकिन मुझे इसके साथ कहीं भी नहीं मिल रहा है। मैं एक समाधान का पता लगाने की कोशिश कर रहा हूं जो दोनों स्थितियों के लिए काम करेगा: कभी-कभी मैं ऑब्जेक्टस्टेट मैनेजर द्वारा ट्रैक की गई ऑब्जेक्ट को अपडेट कर रहा हूं, और कभी-कभी ऐसा नहीं होता है कि यह अभी तक ट्रैक नहीं किया गया है।

Fwiw, मेरा असली भंडार काम करता है, इस तरह दिखेगा बस ऊपर कोड की तरह:

public void Update(T entity) 
{ 
    //works ONLY when entity is not tracked by ObjectStateManager 
    _context.Entry(entity).State = System.Data.EntityState.Modified; 
} 

public void SaveChanges() 
{ 
    _context.SaveChanges(); 
} 

कोई भी विचार? मैं लंबे समय के लिए इस लड़ रहा है ...

उत्तर

12

समस्या यह है कि इस क्वेरी

string thisQueryWillMessThingsUp = 
    context.SaleMethods.Where(m => m.Id == 2).Single().Name; 

संदर्भ में SaleMethod इकाई का एक उदाहरण पेश करती है और उसके बाद इस कोड को

context.Entry(method).State = System.Data.EntityState.Modified; 

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

किसी कारण तुम सिर्फ नाम के लिए क्वेरी करने की जरूरत है, लेकिन वास्तव में संदर्भ में पूर्ण इकाई लाने के लिए नहीं करना चाहते हैं के लिए है, तो आप ऐसा कर सकते हैं, तो:

string thisQueryWillMessThingsUp =   
    context.SaleMethods.Where(m => m.Id == 2).AsNoTracking().Single().Name; 

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

context.Entry(method).State = System.Data.EntityState.Modified; 

से आपको अवगत करवाने नहीं करना चाहते हैं सभी गुण, संभवतः क्योंकि आपके पास सभी गुणों के लिए मूल्य नहीं हैं, फिर पूछताछ करें SaveChanges को कॉल करने से पहले इकाई और सेटिंग गुणों के लिए एक स्वीकार्य दृष्टिकोण है। आपकी सटीक आवश्यकताओं के आधार पर ऐसा करने के कई तरीके हैं। एक तरह से तो जैसे संपत्ति विधि, कुछ का उपयोग करने के लिए है:

http://blogs.msdn.com/b/adonet/archive/2011/01/29/using-dbcontext-in-ef-feature-ctp5-part-4-add-attach-and-entity-states.aspx

http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx

+0

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

+0

यह निर्भर करता है कि क्वेरी का इरादा क्या है। यदि क्वेरी का उद्देश्य किसी इकाई को संदर्भ में लाने का इरादा है ताकि इसे अद्यतन और सहेजा जा सके, जो कि सामान्य है, तो आपको इसके लिए डिज़ाइन करना चाहिए, संभवत: यह सुनिश्चित करने से पहले कि यह सुनिश्चित करने से पहले कि इकाई को लाया गया है, पहले लाया गया था। यदि क्वेरी का इरादा किसी इकाई के संदर्भ में इकाई को बिना किसी कारण के डेटाबेस से इकाई की कुछ संपत्ति प्राप्त करना है, तो ऊपर दिखाए गए अनुसार उस क्वेरी पर AsNoTracking का उपयोग करें। –

+0

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

1

स्पष्ट जवाब होगा कि आपके वास्तव में डेटाबेस के लिए विधि वस्तु बचत नहीं इससे पहले कि आप कहते हैं:

//everything works without this line: 
string thisQueryWillMessThingsUp = context.SaleMethods.Where(m => m.Id == 2).Single().Name; 

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

public abstract class BaseClass 
{ 
    public int Id { get; set; } 
} 

फिर भी आप अपने SaleMethod की आईडी सेट नहीं करना चाह सकते हैं

public class Repository<T> where T : BaseClass 
{ 
..... 
    public void Update(T entity) 
    {   
     _context.Entry(entity).State = entity.Id == 0 ? System.Data.EntityState.Added : System.Data.EntityState.Modified; 
    } 
} 

करने के लिए अपने भंडार को अद्यतन करने और यह डेटाबेस द्वारा उत्पन्न किया जा करते हैं। समस्या यह भी हो सकती है क्योंकि डेटाबेस में SaleMethod ऑब्जेक्ट में आईडी 2 है और फिर आप आईडी 2 के साथ एक और SaleMethod ऑब्जेक्ट जोड़ने का प्रयास करते हैं। आप जो त्रुटि देखते हैं वह ऑब्जेक्टस्टेट मैनेजर में 2 की आईडी के साथ एक और SaleMethod ऑब्जेक्ट जोड़ने की कोशिश करने से उत्पन्न होती है।

+0

प्रतिक्रिया के लिए धन्यवाद:

var salesMethod = context.SaleMethods.Find(2); // Basically equivalent to your query context.Entry(salesMethod).Property(e => e.Name).CurrentValue = newName; context.Entry(salesMethod).Property(e => e.SomeOtherProp).CurrentValue = newOtherValue; context.SaveChanges(); 

ये ब्लॉग पोस्ट कुछ अतिरिक्त जानकारी है कि उपयोगी हो सकता है होते हैं। हां, आईडी निश्चित रूप से डेटाबेस द्वारा जेनरेट की जाती है। यह विशेष रूप से एक ** अद्यतन ** ऑपरेशन है। मैंने उस भाग को छोड़ दिया जहां ऑब्जेक्ट प्रारंभ में सहेजा गया था (प्रारंभ में कोड के दूसरे भाग से पहले सहेजा जा सकता था)। बात यह है कि अपडेट ठीक काम करता है, जब तक कि आप पहले कोई क्वेरी नहीं करते हैं। क्वेरी को निष्पादित करना इसे ऑब्जेक्टस्टेट मैनेजर की ट्रैकिंग में जोड़ता है, जिस बिंदु पर मेरे अपडेट squawks। – Josh

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

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