"एक बयान शरीर के साथ एक लंबोदर अभिव्यक्ति एक अभिव्यक्ति पेड़ में परिवर्तित नहीं किया जा सकता है"


181

EntityFramework का उपयोग करने में , मुझे A lambda expression with a statement body cannot be converted to an expression treeनिम्न कोड को संकलित करने की कोशिश में " " त्रुटि मिलती है :

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}).ToArray();

मुझे नहीं पता कि त्रुटि का क्या अर्थ है और सबसे अधिक इसे कैसे ठीक किया जाए। कोई मदद?


6
इस तरह की सूची में बदलने के लिए प्रयास करें। ऑब्जेक्ट।
लिस्ट

जवाबों:


114

है objectsएक Linq-टू-SQL डेटाबेस संदर्भ? किस मामले में, आप केवल => ऑपरेटर के दाईं ओर सरल अभिव्यक्तियों का उपयोग कर सकते हैं। कारण, इन अभिव्यक्तियों को निष्पादित नहीं किया जाता है, लेकिन डेटाबेस के विरुद्ध निष्पादित होने के लिए SQL में कनवर्ट किया जाता है। इसे इस्तेमाल करे

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();

102

आप IEnumerable संग्रह के लिए लांबा अभिव्यक्ति में स्टेटमेंट बॉडी का उपयोग कर सकते हैं । इसको आजमाओ:

Obj[] myArray = objects.AsEnumerable().Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();

सूचना:
इस विधि का उपयोग करते समय ध्यान से सोचें, क्योंकि इस तरह से, आपके पास मेमोरी में सभी क्वेरी परिणाम होंगे, जिससे आपके बाकी कोड पर अवांछित दुष्प्रभाव हो सकते हैं।


4
+1 मुझे यह पसंद है! जोड़ा जा रहा है AsEnumerable()मेरी समस्या दूर जाना maskes!
जोएल

5
यह वास्तविक समाधान है, स्वीकृत जवाब कुछ मामलों में लागू करना मुश्किल है
फेरन सालगुएरो

15
नहीं, यह असली जवाब नहीं है। यह आपकी क्वेरी को क्लाइंट की ओर से निष्पादित किया जाएगा। विवरण के लिए इस प्रश्न का संदर्भ लें: stackoverflow.com/questions/33375998/…
ल्यूक Vo

1
@DatVM यह इस बात पर निर्भर करता है कि आप क्या करने जा रहे हैं। यह हमेशा सही विकल्प नहीं हो सकता है और निश्चित रूप से हमेशा गलत विकल्प नहीं हो सकता है।
अमीर ओवेसी

3
हालांकि मैं आपसे सहमत हूं, ओपी ने कहा कि वह EntityFramework का उपयोग कर रहा था। अधिकांश मामले, जब ईएफ के साथ काम करते हैं, तो आप चाहते हैं कि डेटाबेस-पक्ष जितना संभव हो उतना काम करे। यह अच्छा होगा यदि आप अपने उत्तर में मामले को नोट करते हैं।
ल्यूक वो

39

इसका मतलब यह है कि आप एक "स्टेटमेंट बॉडी" (यानी लंबो एक्सप्रेशंस, जो घुंघराले ब्रेसिज़ का उपयोग करते हैं) के साथ लैम्ब्डा एक्सप्रेशन का उपयोग उन जगहों पर नहीं कर सकते हैं, जहाँ लैम्ब्डा एक्सप्रेशन को एक्सप्रेशन ट्री में बदलने की ज़रूरत होती है (जो कि लाइनक्वेरीक्कल का उपयोग करते समय उदाहरण के लिए होता है) ।


37
आप ... त्रुटि को थोड़ा दोहराया। @ टिम रोजर्स का जवाब बहुत बेहतर था
vbullinger

2
@vbullinger आप एक हद तक सही हैं, लेकिन अधिक सामान्य अर्थ में (linq-to-sql के संदर्भ के बाहर) यह अधिक प्रत्यक्ष उत्तर है। इसने मुझे एक AutoMapper त्रुटि के साथ मदद की
15

1
vbullinger: इसने मेरी मदद की, हालाँकि।
पॉल

7

आप (Linq2Objects, Linq2Entities, Linq2Sql?) क्या कर रहे हैं, इसके बारे में अधिक जानकारी के बिना, यह काम करना चाहिए:

Arr[] myArray = objects.AsEnumerable().Select(o => {
    var someLocalVar = o.someVar;

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();

11
यह क्वेरी को मूल्यांकन करने के लिए मजबूर करता है।
smartcaveman

हालाँकि, इस परिस्थिति में यह ठीक है, क्योंकि वह वैसे भी ToArray () को सही कहता है।
स्मार्टकेवमैन

2
जरूरी नहीं - कौन जानता है कि "ओ" कितना बड़ा है? यह 50 गुण हो सकता है जब हम सभी चाहते हैं 2.
kdawg

1
इस तकनीक का उपयोग करते समय, मैं उन क्षेत्रों का चयन करना पसंद करता हूं जिन्हें मैं कॉल करने से पहले एक अनाम प्रकार में उपयोग करूंगा.AsEnumerable()
ब्लेक मिशेल

4

चयन के इस अधिभार का उपयोग करें:

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();

यह मेरे लिए काम करता है, लेकिन जब एंटिटी फ्रेमवर्क के साथ उपयोग किया जाता है, तो क्या यह समाधान dbcontext को पहले सभी पंक्तियों को मेमोरी में लोड करने से रोकता है, जैसे कि AsEnumerable () होगा?
संसद

2
@ संवेदनशीलता: स्मृति में सभी पंक्तियों को लोड करने से रोकने के लिए जिसका आपको उपयोग करना चाहिए Expression<Func<Obj,Obj>>
मोहसिन

4

LINQ to SQL रिटर्न ऑब्जेक्ट IQueryableइंटरफ़ेस लागू कर रहे थे । तो Selectविधि के लिए पैरामीटर की भविष्यवाणी करें आपको केवल शरीर के बिना एकल लैम्ब्डा अभिव्यक्ति की आपूर्ति करनी चाहिए।

ऐसा इसलिए है क्योंकि SQL कोड के लिए LINQ SQL सर्वर या अन्य जैसे दूरस्थ पक्ष के बजाय प्रोग्राम के अंदर निष्पादित नहीं होता है। यह आलसी लोडिंग निष्पादन प्रकार IQueryable को लागू करने के द्वारा प्राप्त किया गया था जहां इसकी उम्मीद प्रतिनिधि नीचे की तरह अभिव्यक्ति प्रकार वर्ग में लपेटा जा रहा है।

Expression<Func<TParam,TResult>>

अभिव्यक्ति वृक्ष शरीर के साथ लैम्ब्डा अभिव्यक्ति का समर्थन नहीं करता है और इसकी एकमात्र लाइन लैम्ब्डा अभिव्यक्ति का समर्थन करता है var id = cols.Select( col => col.id );

इसलिए यदि आप कोशिश करते हैं कि निम्न कोड काम नहीं करेगा।

Expression<Func<int,int>> function = x => {
    return x * 2;
}

निम्नलिखित उम्मीद के मुताबिक काम करेगा।

Expression<Func<int,int>> function = x => x * 2;

2

इसका मतलब है कि एक प्रकार की लैम्ब्डा अभिव्यक्ति TDelegateजिसमें एक ([parameters]) => { some code };को परिवर्तित नहीं किया जा सकता है Expression<TDelegate>। यह नियम है।

अपनी क्वेरी को सरल बनाएं। आपके द्वारा प्रदान किया गया निम्नलिखित के रूप में फिर से लिखा जा सकता है और संकलन करेगा:

Arr[] myArray = objects.Select(o => new Obj()
                {
                   Var1 = o.someVar,
                   Var2 = o.var2
                } ).ToArray();

1

है Arrके आधार प्रकार Obj? क्या ओबीजी वर्ग मौजूद है? आपका कोड तभी काम करेगा जब Arr एक प्रकार का Obj हो। आप इसके बजाय यह कोशिश कर सकते हैं:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();

1

आपके विशिष्ट मामले के लिए, बॉडी एक वैरिएबल बनाने के लिए है, और IEnumerableक्लाइंट-साइड पर संसाधित होने के लिए सभी ऑपरेशन को बाध्य करने के लिए स्विच करना , मैं निम्नलिखित समाधान का प्रस्ताव करता हूं।

Obj[] myArray = objects
.Select(o => new
{
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here
    Info = o,
}).Select(o => new Obj()
{
    Var1 = o.SomeLocalVar,
    Var2 = o.Info.var2,
    Var3 = o.SomeLocalVar.SubValue1,
    Var4 = o.SomeLocalVar.SubValue2,
}).ToArray();

संपादित करें: C # कोडिंग कन्वेंशन का नाम बदलें

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