2009-03-30 6 views
5

मान लें कि मेरे पास एक सरणी है, और मैं एक वर्चर के खिलाफ एक LINQ क्वेरी करना चाहता हूं जो वर्चर में कहीं भी सरणी का तत्व है।सरणी तत्वों की LIKE क्वेरी के लिए LINQ

ऐसा कुछ मीठा होगा।

string[] industries = { "airline", "railroad" }

var query = from c in contacts where c.industry.LikeAnyElement(industries) select c

कोई भी विचार?

+0

LINQ से SQL, LINQ से Entities, LINQ से ऑब्जेक्ट्स? – Lucas

उत्तर

5

यह वास्तव में एक उदाहरण मैं अपने "Express Yourself" प्रस्तुति में उपयोग होता है, कुछ है कि नियमित रूप से LINQ में करने के लिए कठिन है के लिए; जहां तक ​​मुझे पता है, ऐसा करने का सबसे आसान तरीका मैन्युअल रूप से भविष्यवाणी लिखना है। मैं नीचे दिए गए उदाहरण का उपयोग करें (ध्यान दें यह StartsWith आदि के लिए समान रूप से काम करेगा):

using (var ctx = new NorthwindDataContext()) 
    { 
     ctx.Log = Console.Out; 
     var data = ctx.Customers.WhereTrueForAny(
      s => cust => cust.CompanyName.Contains(s), 
      "a", "de", "s").ToArray(); 
    } 
// ... 
public static class QueryableExt 
{ 
    public static IQueryable<TSource> WhereTrueForAny<TSource, TValue>(
     this IQueryable<TSource> source, 
     Func<TValue, Expression<Func<TSource, bool>>> selector, 
     params TValue[] values) 
    { 
     return source.Where(BuildTrueForAny(selector, values)); 
    } 
    public static Expression<Func<TSource, bool>> BuildTrueForAny<TSource, TValue>(
     Func<TValue, Expression<Func<TSource, bool>>> selector, 
     params TValue[] values) 
    { 
     if (selector == null) throw new ArgumentNullException("selector"); 
     if (values == null) throw new ArgumentNullException("values"); 
     if (values.Length == 0) return x => true; 
     if (values.Length == 1) return selector(values[0]); 

     var param = Expression.Parameter(typeof(TSource), "x"); 
     Expression body = Expression.Invoke(selector(values[0]), param); 
     for (int i = 1; i < values.Length; i++) 
     { 
      body = Expression.OrElse(body, 
       Expression.Invoke(selector(values[i]), param)); 
     } 
     return Expression.Lambda<Func<TSource, bool>>(body, param); 
    } 

} 
+0

अच्छा! (कृपया दर्ज करें कम से कम 10 अक्षर।) – Lucas

4
from c in contracts 
where industries.Any(i => i == c.industry) 
select c; 

ऐसा कुछ। संग्रह पर किसी भी विधि का प्रयोग करें।

+1

यह LINQ से SQL में अपवाद फेंकता है। इसे "जहां उद्योग" के रूप में लिखा जा सकता है। (सी। इंडस्ट्री) ", जो" सी। इंडस्ट्री इन ('एयरलाइन', 'रेल रोड') के रूप में अनुवाद करता है, लेकिन वह एक तुलना तुलना चाहता है। – Lucas

0

दुर्भाग्य से, जैसे LINQ में समर्थित नहीं है यहां के अनुसार SQL करने के लिए:

http://msdn.microsoft.com/en-us/library/bb882677.aspx

इस के आसपास पाने के लिए आपको एक संग्रहीत प्रक्रिया है जिससे मापदंडों आप में उपयोग करना चाहते हैं स्वीकार करेंगे लिखने के लिए होगा जैसे कथन (ओं) और फिर LINQ से SQL तक कॉल करें।


यह ध्यान दिया जाना चाहिए कि कुछ उत्तरों में कंटेन का उपयोग करने का सुझाव दिया गया है। यह काम नहीं करेगा क्योंकि ऐसा लगता है कि पूरी स्ट्रिंग सरणी तत्व से मेल खाती है। के लिए सरणी तत्व क्षेत्र में ही निहित होने के लिए क्या के लिए देखा जा रहा है, की तरह कुछ:

industry LIKE '%<element>%' 

क्लार्क के रूप में एक टिप्पणी में उल्लेख किया है, तो आप प्रत्येक तत्व पर indexOf के लिए एक कॉल इस्तेमाल कर सकते हैं (जो का अनुवाद करना चाहिए किसी SQL कॉल करने के लिए):

string[] industries = { "airline", "railroad" } 

var query = 
    from c in contacts 
    where 
     c.industry.IndexOf(industries[0]) != -1 || 
     c.industry.IndexOf(industries[1]) != -1 

आप सरणी की लंबाई और तत्वों की संख्या पता है, तो आप इस हार्ड-कोड कर सकते थे। यदि आप नहीं करते हैं, तो आपको सरणी और उस क्षेत्र के आधार पर अभिव्यक्ति उदाहरण बनाना होगा जिसे आप देख रहे हैं।

WHERE 'american airlines' IN ('airline', 'railroad') -- FALSE 

String.Contains() जिसमें के रूप में% की तरह एसक्यूएल करने के लिए अनुवाद ...%:

+0

मुझे पता था कि .. मेरा बुरा .. सरणी में प्रत्येक आइटम के लिए एक charindex! = -1 बस ठीक होगा। – Clark

+1

वास्तव में LIKE कुछ हद तक LINQ से SQL में समर्थित है। "जहां c.industry.Contains (" एयरलाइन ")" काम करता है और अनुवाद करता है "जहां सी। इंडस्ट्री पसंद है '% एयरलाइन%'। लेकिन वह किसी भी दिए गए मानों की तरह नहीं चाहता, न केवल एक। – Lucas

3

IEnumerable.Contains() में के रूप में में एसक्यूएल करने के लिए अनुवाद

WHERE 'american airlines' LIKE '%airline%' -- TRUE 

आप संपर्कों जहां चाहते हैं संपर्क का उद्योग किसी भी उद्योग में शामिल है (इसमें शामिल है), आप किसी भी() और स्ट्रिंग.कॉन्टेन() दोनों को इस तरह से जोड़ना चाहते हैं:

string[] industries = { "airline", "railroad" }; 

var query = from c in contacts 
      where industries.Any(i => c.Industry.Contains(i)) 
      select c; 

हालांकि, इस तरह दोनों किसी भी() और String.Contains() के संयोजन नहीं एसक्यूएल करने के लिए LINQ में समर्थित है। दिए गए उद्योगों के सेट छोटा है, तो आप की तरह कुछ की कोशिश कर सकते हैं:

where c.Industry.Contains("airline") || 
     c.Industry.Contains("railroad") || ... 

या (हालांकि सामान्य रूप से अनुशंसित नहीं) करता है, तो संपर्क का सेट काफी छोटा है, तो आप उन सब को डीबी से ला सकता है और फिल्टर लागू संपर्कों का उपयोग करके LINQ से ऑब्जेक्ट्स के साथ। अनन्य() या संपर्क।ToList() ऊपर क्वेरी के स्रोत के रूप में:

var query = from c in contacts.AsEnumerable() 
      where industries.Any(i => c.Industry.Contains(i)) 
      select c; 
1

यदि आप इस प्रकार क्वेरी का निर्माण यह काम करेगा: contacts.AsEnumerable में

वर क्वेरी = c से() सी का चयन करें;

क्वेरी = क्वेरी। जहां (सी => (सी। इंडस्ट्रीज। कंटेनेंस ("एयरलाइन")) || (सी। इंडस्ट्री। कंटेनर ("रेल रोड"));

पैरामीटर एयरलाइन और रेलरोड उपयोगकर्ता इनपुट हैं, तो आपको उपरोक्त स्ट्रिंग को प्रोग्रामेटिक रूप से उत्पन्न करने की आवश्यकता है। यह वास्तव में अपेक्षा की तुलना में थोड़ा अधिक जटिल था। लेख देखें - http://www.albahari.com/nutshell/predicatebuilder.aspx

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

  • कोई संबंधित समस्या नहीं^_^