Linq Select में एक Tuple बनाएं


89

मैं C # और .NET फ्रेमवर्क के साथ काम कर रहा हूँ। 4.5.1 इकाई फ्रेमवर्क 6.1.3 के साथ SQL सर्वर डेटाबेस से डेटा पुनर्प्राप्त कर रहा है।

मेरे पास यह है:

codes = codesRepo.SearchFor(predicate)
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

और जब मैं इसे चलाता हूं, मुझे यह संदेश मिलता है:

LINQ से Entities तक केवल पैरामीटर रहित कन्स्ट्रक्टर और इनिशियलाइज़र समर्थित हैं।

मुझे नहीं पता कि मुझे टपल कैसे बनाना है क्योंकि मेरे द्वारा पाए गए सभी उदाहरण ज्यादातर इसी तरह हैं।

मैंने यह कोशिश की है:

codes = codesRepo.SearchFor(predicate)
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();

और यह त्रुटि प्राप्त करें:

LINQ से Entities विधि 'System.Tuple`2 [System.String, System.Byte] बनाएँ [स्ट्रिंग, बाइट] (System.String, बाइट) विधि को मान्यता नहीं देता है, और इस पद्धति को स्टोर अभिव्यक्ति में अनुवादित नहीं किया जा सकता है।

समस्या कहाँ हे?


ऐसा लगता है कि आपको एक जोरदार टाइप की गई वस्तु बनाने की आवश्यकता होगी। लेकिन हां, अच्छा सवाल; upvoted।
फ्रेंच

जवाबों:


121

हालांकि ऑक्टावोक्कल द्वारा जवाब काम करता है, पहले क्वेरी परिणाम को गुमनाम प्रकार में प्रोजेक्ट करना बेहतर होता है, और फिर गणना करने और स्विच करने के लिए इसे ट्यूपल में बदल देता है। इस तरह आपकी क्वेरी डेटा बेस से केवल आवश्यक फ़ील्ड से पुनर्प्राप्त होगी।

codes = codesRepo.SearchFor(predicate)
    .Select(c => new { c.Id, c.Flag })
    .AsEnumerable()
    .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
    .ToList();

नोट: उपरोक्त नियम EF6 पर लागू होता है। EF कोर स्वाभाविक रूप से tuples का समर्थन करता है (प्रक्षेपण में या शामिल / समूह कुंजी के रूप में) tuple constructor के माध्यम से, जैसे मूल क्वेरी बस काम करती है

codes = codesRepo.SearchFor(predicate)
  .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
  .ToList();

लेकिन Tuple.Createविधि नहीं (EF Core 2.x)।


बहुत अच्छा समाधान - धन्यवाद! ... क्या होगा अगर मुझे इस समाधान को एक और अशक्त मूल्य से विस्तारित करना पड़ा? .Select(c => new { c.Id, c.Flag, c.Foo?.Code })काम नहीं करता।
स्काईफ्रॉग

2
@skyfrog संचालक ?.अभिव्यक्ति पेड़ों में समर्थित नहीं है। लेकिन इसके अलावा, आप गुमनाम प्रकार का विस्तार कर सकते हैं जितने मूल्यों के साथ आप चाहते हैं - बस डॉन; उन्हें नाम न भूलें जब जरूरत हो :) उदाहरण के लिएc => new { c.Id, c.Flag, Code = (int?)c.Foo.Code }
इवान स्टोव

1
महान! आपके उत्तर के लिए बहुत धन्यवाद @ इवान। मैंने बस कर ही दिया था! ... लेकिन पीछे मुड़कर
देखना

महान जवाब, ईएफ-एंटिटीज के साथ इस्तेमाल किया जा सकता है .. जैसे dbCtx.MyEntity.Where () (चयन करें (.. एनॉन ऑब्जेक्ट ...) के लिए। आदि ...
joedotnot

50

C # 7 के लिए बस एक अद्यतन उत्तर, अब आप ValueTuples बनाने के लिए एक सरल वाक्यविन्यास का उपयोग कर सकते हैं।

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (c.Id, c.Flag))
.ToList();

आप अब टपल के गुणों को भी नाम दे सकते हैं:

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag }) // anonymous type
.AsEnumerable()
.Select(c => (Id: c.Id, Flag: c.Flag)) // ValueTuple
.ToList();

इसलिए इसे Item1 या Item2 के रूप में उपयोग करने के बजाय आप इसे Id या Flag के रूप में एक्सेस कर सकते हैं।

अनाम-और-अनाम-ट्यूपल चुनने पर अधिक डॉक्स


11

इसे इस्तेमाल करे:

codes = codesRepo.SearchFor(predicate)
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();

LINQ को सूचित नहीं किया गया है कि वह संस्थाओं को LINQ में स्वीकार नहीं कर रहा है।

एक अन्य विकल्प यह होगा कि चयन से पहले परिणाम को स्मृति में खींच लिया जाए। यदि आप ऐसा करने जा रहे हैं, तो मैं फ़िल्टरिंग के सभी करने की सलाह दूंगा .AsEnumerable () के रूप में इसका मतलब है कि आप केवल वापस परिणाम खींच रहे हैं जिसे आप पूरी तालिका को वापस खींचने के लिए विरोध करना चाहते हैं और फिर फ़िल्टर करना चाहते हैं।

codes = codesRepo.SearchFor(predicate).AsEnumerable()
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();

साथ ही Tuple.Create (c.Id, c.Flag) को नए Tuple (c.Id, c.Flag) में बदला जा सकता है, यदि आप कोड को थोड़ा अधिक स्पष्ट करना चाहते हैं


क्षमा करें, यह काम नहीं करता है। मैंने अधिक विवरण के साथ अपना प्रश्न अपडेट किया है।
VansFannel

10

में संस्थाओं के लिए LINQ आप एक गुमनाम प्रकार पर या एक DTO.To से बचने कि जारी आप उपयोग कर सकते हैं पर पेश कर सकती हैं AsEnumerableविस्तार विधि:

codes = codesRepo.SearchFor(predicate).AsEnumerable().
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

यह विधि आपको Linq के साथ Entities के बजाय Linq के साथ काम करने की सुविधा देती है , इसलिए इसे कॉल करने के बाद, आप अपनी क्वेरी का परिणाम जो भी आप की आवश्यकता हो सकती है। AsEnumerableइसके बजाय उपयोग करने ToListका लाभ यह है कि AsEnumerableक्वेरी निष्पादित नहीं करता है, यह स्थगित निष्पादन को संरक्षित करता है। यह अच्छा विचार है कि इनमें से किसी एक तरीके को कॉल करने से पहले अपने डेटा को हमेशा फ़िल्टर करें।


-1 यह वही काम नहीं करता जैसा ओपी ने पूछा था। जुड़ने के प्रयोजनों के लिए कभी-कभी, एक प्रश्न में ट्यूपल्स बनाने में सक्षम होना महत्वपूर्ण है।
एरन


1

ऐसा करने के लिए इस विधि का उपयोग करें और async का उपयोग करें।

var codes = await codesRepo.SearchFor(predicate)
                    .Select(s => new
                    {
                        Id = s.Id,
                        Flag = s.Flag
                    }).FirstOrDefaultAsync();

                var return_Value = new Tuple<string, byte>(codes.Id, codes.Flag);

0

बस मेरे दो सेंट: इसने मुझे कुछ बार टाइप नामों के साथ पकड़ा है:

कुछ नोडली उदाहरण:

    private Tuple<string, byte> v1()
    {
        return new Tuple<string, byte>("", 1);
    }

    private (string, int) v2()
    {
        return ("", 1);
    }

    private (string Id, byte Flag) v3()
    {
        return ("", 1);
    }

सादर।


आपके द्वारा पोस्ट किया गया सिंटैक्स काम नहीं करता है। आप शायद लिखने के लिए क्या चाहते हैं public (string Id, byte Flag) SearchFor(Expression predicate), लेकिन यह बिंदु के बगल में है। दो सेंट एक जवाब नहीं होना चाहिए, लेकिन एक टिप्पणी है।
एम। संतराम

2
मैंने अपना उत्तर अपडेट किया - मुझे पोस्ट करने से पहले इसकी जाँच करनी चाहिए थी। मैं असहमत हूं; सभी जानकारी सभी आगंतुकों के लिए उपयोगी है, जो इस पृष्ठ पर परवाह किए बिना कि यह कैसे प्रस्तुत किया जाता है। टिप्पणियां इरादे के साथ-साथ उत्तर के लिए धन्यवाद नहीं व्यक्त करती हैं।
IbrarMumtaz

मैं मानता हूँ कि जोड़ा गया सामग्री अच्छी है और टिप्पणियाँ कोड के उदाहरणों को अच्छी तरह से पूरा नहीं करती हैं। संपादन के लिए धन्यवाद, अब यह स्पष्ट है कि यह ओपी के सवाल का जवाब नहीं है (लेकिन टपल संबंधित समस्याओं के साथ मदद कर सकता है)।
M.Stramm
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.