2013-06-13 6 views
8

पर कॉल करें, मैं पृष्ठ पर उत्पादों की पहले लोड की गई सूची से अलग-अलग रंगों की सूची लोड करने का प्रयास कर रहा हूं। तो उत्पादों मैं यह करने में खींचने के लिए:इकाई फ्रेमवर्क AsNoTracking ब्रेक को अलग-अलग

var products = Products 
    .Include(p => p.ProductColor) 
    .ToList(); 

तो मैं उत्पादों पर उन्हें कुछ प्रसंस्करण कर मैं अलग उत्पादों के द्वारा प्रयुक्त रंग के सभी की एक सूची प्राप्त करना चाहते हैं, तो मैं ऐसा करते हैं:

var colors = products 
    .Select(p => p.ProductColor) 
    .Distinct(); 

और यह बहुत अच्छा काम करता है, हालांकि अगर मैं मूल उत्पाद कॉल में .AsNoTracking() पर कॉल जोड़ता हूं, तो अब मुझे उत्पाद सूची में प्रत्येक प्रविष्टि के लिए मेरी रंग सूची में एक प्रविष्टि मिलती है।

इन दोनों में कोई अंतर क्यों है? क्या एंटीटी फ्रेमवर्क ऑब्जेक्ट्स को ट्रैक करने से रोकने का कोई तरीका है (वे केवल पढ़ने के लिए उपयोग किए जा रहे हैं) और वांछित व्यवहार प्राप्त करने के लिए?

यहाँ AsNoTracking()

var products = Products 
    .AsNoTracking() 
    .Include(p => p.ProductColor) 
    .ToList(); 
+0

जो आपने पोस्ट किया है उससे .एएसएनओट्रैकिंग को ठीक काम करना चाहिए, जहां आप इसे अपनी क्वेरी –

+0

@LukeMcGregor में डाल रहे हैं, मैंने अपनी क्वेरी के साथ प्रश्न को अपडेट किया है .एएसएनओट्रैकिंग – heavyd

+0

क्या यह सिर्फ एक टाइपो है क्वेरी टोलिस्ट के साथ समाप्त होती है और इसमें कोई विशिष्ट नहीं है? –

उत्तर

19

AsNoTracking "ब्रेक" Distinct क्योंकि AsNoTracking "ब्रेक" पहचान मानचित्रण करने के लिए कॉल को जोड़ने के बाद अपनी क्वेरी है। चूंकि AsNoTracking() के साथ लोड की गई संस्थाएं संदर्भ कैश से जुड़ी नहीं होंगी, ईएफ क्वेरी से लौटाई गई प्रत्येक पंक्ति के लिए नई इकाइयों को पूरा करता है, जबकि ट्रैकिंग सक्षम होने पर यह जांच करेगा कि संदर्भ में एक ही कुंजी मान वाली इकाई पहले से मौजूद है और यदि हां , यह एक नई वस्तु नहीं बनाएगा और इसके बजाय संलग्न ऑब्जेक्ट उदाहरण का उपयोग करेगा।

उदाहरण के लिए, आप 2 उत्पादों है और यदि दोनों ग्रीन हैं: 2 Product वस्तुओं और 1 ProductColor वस्तु (ग्रीन):

  • AsNoTracking() आपकी क्वेरी के बिना 3 वस्तुओं अमल में लाना होगा। उत्पाद 1 (ProductColor संपत्ति में) ग्रीन के लिए एक संदर्भ है और उत्पाद 2 एक ही वस्तु उदाहरण ग्रीन के लिए एक संदर्भ है, यानी

    object.ReferenceEquals(product1.ProductColor, product2.ProductColor) == true 
    
  • AsNoTracking() साथ

    आपकी क्वेरी 4 वस्तुओं अमल में लाना होगा: 2 उत्पाद वस्तुओं और 2 रंग वस्तुओं (दोनों ग्रीन का प्रतिनिधित्व करते हैं और एक ही महत्वपूर्ण मूल्य है)। उत्पाद 1 (ProductColor संपत्ति में) ग्रीन के लिए एक संदर्भ है और उत्पाद 2 ग्रीन के लिए एक संदर्भ है, लेकिन इस किसी अन्य वस्तु उदाहरण

    object.ReferenceEquals(product1.ProductColor, product2.ProductColor) == false 
    

है अब यानी,, यदि आप में एक संग्रह पर Distinct() फोन स्मृति (LINQ-to-Objects) पैरामीटर के बिना Distinct() के लिए डिफ़ॉल्ट तुलना ऑब्जेक्ट संदर्भ पहचान की तुलना कर रही है। तो, यदि आपको 1 केवल 1 ग्रीन ऑब्जेक्ट मिलता है, लेकिन 2 मामले में आपको 2 ग्रीन ऑब्जेक्ट मिलेंगे।

के बाद क्या आप इकाई कुंजी के द्वारा एक तुलना की जरूरत है AsNoTracking() साथ क्वेरी चलाने वांछित परिणाम प्राप्त करने के लिए। आप या तो Distinct के दूसरे अधिभार का उपयोग कर सकते हैं जो पैरामीटर के रूप में IEqualityComparer लेता है। इसके क्रियान्वयन के लिए एक उदाहरण here है और आप दो वस्तुओं की तुलना करने के लिए ProductColor की प्रमुख संपत्ति का उपयोग करेंगे।

या - जो थकाऊ IEqualityComparer कार्यान्वयन की तुलना में मेरे लिए आसान लगता है - आप एक GroupBy (समूह कुंजी के रूप में साथ ProductColor कुंजी संपत्ति) का उपयोग कर Distinct() पुनर्लेखन:

var colors = products 
    .Select(p => p.ProductColor) 
    .GroupBy(pc => pc.ProductColorId) 
    .Select(g => g.First()); 

First() मूल रूप से मतलब है कि आप कर रहे हैं सभी डुप्लिकेट को फेंक दें और केवल प्रति ऑब्जेक्ट आवृत्ति को प्रति प्रमुख मान रखें।

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