2009-02-28 15 views
11

मेरे पास एक कोर्स टेबल है जिसे मुझे खोज बॉक्स में टाइप किए गए कीवर्ड के आधार पर खोजना है।LINQ एकाधिक जहां खंड

SELECT * FROM Courses WHERE 
Title LIKE '%word%' OR Title LIKE '%excel%' OR 
Contents LIKE '%word%' OR Contents LIKE '%excel%' 

मैं कैसे LINQ में परिवर्तित जहां LINQ गतिशील रूप से प्रत्येक कीवर्ड के आधार पर जहां बयान उत्पन्न होगा कर सकते हैं: यहाँ एक नमूना क्वेरी है।

मैंने उपयोगकर्ता को भविष्यवाणी करने की कोशिश की, जब तक कि क्षेत्र VARCHAR है, तब तक यह ठीक काम करता है। "टेक्स्ट" फ़ील्ड के लिए उद्धरण उत्पन्न नहीं होते हैं जिससे संकलक को त्रुटि संदेश देने का कारण बनता है। यहाँ PredicateBuilder

SELECT [t0].[CoursesID], [t0].[Title], [t0].[Contents], [t0].[Active], 
FROM [dbo].[Courses] AS [t0] 
WHERE ([t0].[Title] LIKE '%word%') OR ([t0].[Contents] LIKE %word%) OR 
([t0].Title] LIKE '%excel%') OR ([t0].[Contents] LIKE %excel%) 

सूचना द्वारा उत्पन्न एसक्यूएल "सामग्री" क्षेत्र है जो डेटाबेस में एक पाठ क्षेत्र है के लिए कोई एक उद्धरण वहाँ जाता है।

क्या WHERE कथन बनाने और क्वेरी के साथ संलग्न करने का कोई आसान तरीका है? क्या किसी को पता है कि मैं PredicateBilder के बिना यह कैसे कर सकता हूं?

अग्रिम धन्यवाद।

उत्तर

13

चूंकि आप काम कर रहे हैं w/LINQ मुझे लगता है कि आप LINQ-to-SQL डेटा संदर्भ के विरुद्ध काम कर रहे हैं? मेरे पास परीक्षण करने के लिए चारों ओर एक अतिरिक्त डेटाकॉन्टेक्स्ट नहीं है, लेकिन इससे आपको कुछ विचार मिलेंगे।

मुझे नहीं पता कि यह डेटा संदर्भ के खिलाफ काम करेगा या नहीं, लेकिन इनमें से अधिकतर मूलभूत सामग्री (चेनिंग या ऑपरेटर और विधि कॉल शामिल हैं) इसलिए क्वेरी को एसक्यूएल में अनुवाद करते समय समस्या का कारण नहीं बनना चाहिए।

Func<string, Func<DataItem, bool>> buildKeywordPredicate = 
    keyword => 
     x => x.Title.Contains(keyword) 
      || x.Contents.Contains(keyword); 

यह एक समारोह जो एक एकल स्ट्रिंग कीवर्ड लेता है और फिर एक और समारोह जो एक DataItem लेता है और कीवर्ड से करता है वापसी है:

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

असल में, यदि आप "स्टैक" में पास करते हैं, तो आपको एक अनुमान मिलेगा: x => x.Title.Contains("Stack") || x.Contents.Contains("Stack")

इसके बाद, के बाद से वहाँ कई संभावित कीवर्ड हैं और आप एक या ऑपरेशन के साथ यह श्रृंखला की जरूरत है, मैं श्रृंखला के लिए एक और सहायक समारोह 2 विधेय एक साथ बनाने के साथ एक या

Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate = 
    (pred1, pred2) => 
     x => pred1(x) || pred2(x); 

इस समारोह 2 विधेय लेता है और उसके बाद एक या ऑपरेशन के साथ उनसे जुड़ें।

उन 2 कार्यों के बाद, मैं तो निर्माण कर सकते हैं मेरी जहां इस तरह विधेय:

foreach (var word in keywords) {    
    filter = filter == null 
     ? buildKeywordPredicate(word) 
     : buildOrPredicate(filter, buildKeywordPredicate(word)); 
} 

अगर फिल्टर रिक्त है पाश अंदर पहली पंक्ति मूल रूप से जाँच करता है। यदि ऐसा है, तो हम हमारे लिए बनाया गया एक साधारण कीवर्ड फ़िल्टर चाहते हैं।

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

और फिर हम अब क्वेरी के WHERE हिस्सा बना सकते हैं:

var result = data.Where(filter); 

जटिल विधेय हम सिर्फ निर्माण किया है में पासिंग।

मुझे नहीं पता कि यह PredicateBuilder का उपयोग करने से अलग होगा या नहीं, लेकिन चूंकि हम LINQ-to-SQL इंजन में क्वेरी अनुवाद का निर्धारण कर रहे हैं, तो कोई समस्या नहीं होनी चाहिए।

लेकिन जैसा कि मैंने कहा, मैंने इसे वास्तविक डेटा संदर्भ के खिलाफ परीक्षण नहीं किया है, इसलिए यदि कोई समस्या है तो आप टिप्पणियों में लिख सकते हैं। http://pastebin.com/feb8cc1e

आशा इस मदद करता है:

यहाँ सांत्वना अनुप्रयोग है कि मैं परीक्षण करने के लिए बनाया गया है!


संपादित करें: एक अधिक सामान्य और पुन: प्रयोज्य संस्करण है जो ठीक से LINQ में अभिव्यक्ति पेड़ का उपयोग करना शामिल है के लिए, थॉमस Petricek के ब्लॉग पोस्ट की जाँच: http://tomasp.net/articles/dynamic-linq-queries.aspx

+1

यह Unfortunatelly कार्यों के लिए केवल काम करेंगे। अभिव्यक्ति पेड़ों के साथ यह काम करने के लिए आपको इस तरह की चाल का उपयोग करने की आवश्यकता है: http://tomasp.net/articles/dynamic-linq-queries.aspx –

+0

यह कुछ काम है जो आपने वहां किया था! .. एक ही चाल लेकिन अधिक सामान्य और अधिक उत्कृष्टता ... वैसे भी, मैं अब आपके ब्लॉग का ग्राहक हूं :-) – chakrit

+0

धन्यवाद, यह एक काम किया। http://tomasp.net/articles/dynamic-linq-queries.aspx - टॉमस पेट्रिसक – Amir

0

अनुमान के अनुसार बिल्डर संपत्ति के डीबी प्रकार को नहीं जानता है जिसमें विधि विधि शामिल है, मुझे लगता है कि यह linq के अंदर sql के अंदर एक समस्या हो सकती है। क्या आपने सामान्य क्वेरी (अनुमानित बिल्डर के साथ नहीं) और एक टेक्स्ट कॉलम के साथ प्रयास किया है?

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