2012-02-11 12 views
32

मैं लैंबडा अभिव्यक्ति के साथ इस linq क्वेरी को Entity पर कैसे लिख सकता हूं?
मैं कीवर्ड या मेरे लैम्ब्डा अभिव्यक्ति में समकक्ष का उपयोग करना चाहता हूं।लैम्ब्डा अभिव्यक्ति में "चलो" कैसे करें?

var results = from store in Stores 
       let AveragePrice = store.Sales.Average(s => s.Price) 
       where AveragePrice < 500 && AveragePrice > 250 

क्या मेरे सवाल के तहत टिप्पणी की है जैसे कुछ इसी तरह के सवाल के लिए, यह

.Select(store=> new { AveragePrice = store.Sales.Average(s => s.Price), store}) 

जो प्रत्येक आइटम के लिए AveragePrice की गणना करेगा, जबकि क्वेरी शैली में मैंने कहा करने का सुझाव दिया है, जाने अभिव्यक्ति को रोकता है औसत कई बार गणना करें।

+2

संभव डुप्लिकेट श्रृंखलाबद्ध LINQ एक्सटेंशन विधि कॉल में 'चलो' कीवर्ड] (http://stackoverflow.com/questions/1092687/code-equivalent-to-the-let-keyword-in-chained-linq-extension-method-calls) – Eranga

+0

@ एरंगा: मैं वह प्रश्न, मार्क ने प्रत्येक आइटम के लिए पशु नाम का चयन किया था। यहां, मैं प्रत्येक आइटम के लिए सभी वस्तुओं की औसत गणना नहीं करना चाहता हूं। –

+1

@Reza: औसत प्रति स्टोर ऑब्जेक्ट की गणना केवल एक बार आपके क्वेरी में की जाती है ... – digEmAll

उत्तर

36

तो, आप विस्तार विधि वाक्यविन्यास का उपयोग कर सकते हैं, जिसमें वर्तमान में आप एक लैम्ब्डा अभिव्यक्ति को शामिल कर सकते हैं। कोई let है, तो आप सिर्फ एक बहु लाइन लैम्ब्डा का उपयोग करें और एक चर घोषित:

var results = Stores.Where(store => 
{ 
    var averagePrice = store.Sales.Average(s => s.Price); 
    return averagePrice > 250 && averagePrice < 500; 
}); 

ध्यान दें कि मैं औसत मूल्य की तुलना बदल गया है, क्योंकि तुम्हारा कोई फल प्राप्त कभी नहीं होगा (500 से अधिक और कम है कि 250) ।

विकल्प

var results = Stores.Select(store => new { Store = store, AveragePrice = store.Sales.Average(s => s.Price}) 
    .Where(x => x.AveragePrice > 250 && x.AveragePrice < 500) 
    .Select(x => x.Store); 
+4

त्रुटि: एक कथन निकाय के साथ एक लैम्ब्डा अभिव्यक्ति को अभिव्यक्ति वृक्ष में परिवर्तित नहीं किया जा सकता है। –

+5

आपका पहला प्रस्ताव सिर्फ स्मृति पर काम करता है और ईएनएफ जैसे LINQ प्रदाताओं में उपयोग नहीं किया जा सकता था। एक कथन निकाय के साथ एक लैम्ब्डा अभिव्यक्ति को अभिव्यक्ति वृक्ष में परिवर्तित नहीं किया जा सकता है। –

+0

@Jay: सभी वस्तुओं के AvaragePrice दूसरे विकल्प के अनुसार प्रत्येक आइटम के लिए गणना की जा रही है। मैं इस गणना को दोहराने से रोकने के लिए * let * जैसे कुछ उपयोग करना चाहता हूं। –

19

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

जांची नहीं है, लेकिन यह इस तरह दिखना चाहिए:

Stores.Select(
x => new { averagePrice = x.Sales.Average(s => s.Price), store = x}) 
.Where(y => y.averagePrice > 500 && y.averagePrice < 250) 
.Select(x => x.store); 

चेतावनी, इन निर्माणों के साथ सावधान रहना। का उपयोग करते हैं जानकारी के लिए यहां अपने संग्रह में वस्तु प्रति एक नई अज्ञात प्रकार बनाता है, जिसे बड़े संग्रह के साथ स्मृति का एक बहुत की खपत ...

देखो: Let in chained extension methods

+0

यह * किसी भी * स्मृति का उपभोग नहीं करता है अगर वे LINQ-to- संस्थाओं के प्रश्न या समान। – svick

+2

वास्तव में, केवल linq-to-objects के लिए यह है। Thx – Yoeri

+1

यह स्वीकार्य उत्तर होना चाहिए, क्योंकि यह आपको अपने चर का उपयोग विभिन्न "खंड" में करने देता है। – alexbchr

3

एक अन्य विकल्प इस विस्तार विधि को परिभाषित करने के लिए है:

public static class Functional 
{ 
    public static TResult Pipe<T, TResult>(this T value, Func<T, TResult> func) 
    { 
     return func(value); 
    } 
}  

तो इस तरह आपकी क्वेरी लिखें:

var results = Stores 
    .Where(store => store.Sales.Average(s => s.Price) 
     .Pipe(averagePrice => averagePrice < 500 && averagePrice > 250)); 
[कोड बराबर के
संबंधित मुद्दे