LINQ केस असंवेदनशील होता है


174

यह कोड संवेदनशील है, इसे असंवेदनशील कैसे बनाया जाए?

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM.Where(fi => fi.DESCRIPTION.Contains(description));
}

Sjoerd के उत्तर सही हैं लेकिन ... मैं i और इसके विपरीत लिखते समय तुर्की d (उदाहरण के लिए) वाले नामों के लिए खोज परिणाम प्राप्त करना चाहता हूं। इस मामले में ToLower जाने का सही तरीका प्रतीत होता है। कृपया मुझे सुधारें अगर मैं गलत हूं। तुर्की के बारे में
w

@ हेनेरिक - जैसा कि स्वीकार किए गए जवाब के तहत Jyelton की टिप्पणी में तुर्की टेस्ट लिंक पर चर्चा की गई है, जब तुर्की संस्कृति के साथ चलाया जाता है, तो उन दो मैं अलग होंगे - इसलिए आपको दूसरे के साथ नाम नहीं मिलेंगे। आप ToLowerInvariant चाहते हैं। विभिन्न उत्तरों के तहत चर्चा यहाँ देखें ।
टूलमेकरसैट

यह एक पुराना प्रश्न है, लेकिन यह ध्यान देने योग्य है कि वर्तमान संस्करण में EF कोर 2.0 ToLower () निम्नानुसार काम करता है। व्यक्ति (p => p.Name.ToLower) () शामिल हैं। )); मैं एक Postgres DB के खिलाफ एक Linq क्वेरी में इसका उपयोग कर रहा हूं। मेरे पास डीबी में कॉलम के टकराव पर असंवेदनशीलता का मामला नहीं है और मैंने जांच की कि टोलवर () के बिना मैच स्पष्ट रूप से संवेदनशील है।
आश्रयदीप

जवाबों:


72

यह मानते हुए कि हम यहां स्ट्रिंग्स के साथ काम कर रहे हैं, यहां एक और "सुरुचिपूर्ण" समाधान का उपयोग कर रहे हैं IndexOf()

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
        .Where(fi => fi.DESCRIPTION
                       .IndexOf(description, StringComparison.OrdinalIgnoreCase) != -1);
}

7
अच्छा लगा। हालांकि मेरे अपने उद्देश्यों के लिए, यह LINQ से लेकर संस्थाओं तक के लिए काम नहीं करता है। LINQ के लिए अच्छा समाधान हालांकि वस्तुओं के लिए।
डेमियन पॉवेल

242
fi => fi.DESCRIPTION.ToLower().Contains(description.ToLower())

49
जैसा कि जॉन स्कीट ने एक संबंधित प्रश्न पर टिप्पणी की थी , यह विधि तुर्की टेस्ट पास नहीं करेगी ।
येल्टन

5
नहीं, लेकिन डेटाबेस वर्ण सेट और टकराव से दूर काम करते हैं। यदि आप डेटाबेस के लिए काम बंद करने की कोशिश कर रहे हैं, तो आपको वर्ण सेट और टकराव के बारे में कुछ धारणाएं बनानी होंगी, है ना?
क्रिस्टोफर स्टीवेन्सन

66
IEqualityComparer<string>तुलनात्मकता कैसे काम करेगी, इसे संभालने के लिए विशेषता का उपयोग करना चाहिए । समानता की जाँच करने के लिए ToLower और ToUpper का उपयोग करना एक बुरा विचार है। प्रयास करें: .Contains(description, StringComparer.CurrentCultureIgnoreCase)उदाहरण के लिए
डोरिवल

19
@ डोरिवल नॉट वर्क का कमेंट, क्योंकि यह इस तरह की गलतफहमी देता है:Error 1 'string' does not contain a definition for 'Contains' and the best extension method overload 'System.Linq.ParallelEnumerable.Contains<TSource>(System.Linq.ParallelQuery<TSource>, TSource, System.Collections.Generic.IEqualityComparer<TSource>)' has some invalid arguments
eMi

6
Containsसाथ StringComparerपैरामीटर के रूप में स्ट्रिंग प्राप्त नहीं होता है, तो यह निर्माण त्रुटि हो जाएगा। IndexOfपर Queryableशायद एसक्यूएल में अनुवाद नहीं किया जा सकता है। व्यक्तिगत रूप से मुझे यह उत्तर पूरी तरह से मान्य लगा क्योंकि हम डेटाबेस में LINQ के बारे में बोलते हैं।
थारिक नुगरोतोमो

122

यदि LINQ क्वेरी को डेटाबेस संदर्भ में निष्पादित Contains()किया जाता है, तो LIKEऑपरेटर को कॉल करने के लिए मैप किया जाता है :

.Where(a => a.Field.Contains("hello")) बन जाता है Field LIKE '%hello%'LIKEऑपरेटर डिफ़ॉल्ट रूप से केस संवेदी है, लेकिन उस से बदला जा सकता स्तंभ का मिलान बदल रहा है

यदि LINQ क्वेरी को .NET संदर्भ में निष्पादित किया जाता है, तो आप IndexOf () का उपयोग कर सकते हैं , लेकिन यह विधि LINQ से SQL में समर्थित नहीं है।

LINQ to SQL एक तरीके का समर्थन नहीं करता है जो कि CultureInfo को पैरामीटर के रूप में लेता है, शायद इसलिए यह गारंटी नहीं दे सकता है कि SQL सर्वर संस्कृतियों को उसी .NET के रूप में संभालता है। यह पूरी तरह सच नहीं है, क्योंकि यह समर्थन करता हैStartsWith(string, StringComparison)

हालांकि, यह एक ऐसी विधि का समर्थन नहीं करता है जो LIKELINQ से SQL में मूल्यांकन करता है, और .NET में असंवेदनशील तुलना के मामले में, असंवेदनशील समसामयिक तरीके से केस असंवेदनशील () करना असंभव बनाता है।


सिर्फ FYI EF 4.3 स्टार्टस्विथ का समर्थन नहीं करता है। मुझे मिलता है: LINQ से लेकर संस्थाएँ 'बुलियन स्टार्टस्विथ (सिस्टम.ट्रिंग,
सिस्टम.ट्रिंग कॉमपैरिसन

StartWith LIKE 'हैलो%' में कनवर्ट करता है?
बार्ट कैलिक्सो

clicdata लिंक मृत है।
एडम पार्किन

2
LIKE खण्ड के लिए उत्पन्न SQL और db व्यवहार में खुदाई के लिए महान प्रयास
Thariq Nugrohotomo

1
ईएफ का उपयोग करते समय लोगों के पास क्या विकल्प हैं, एक संदर्भ में मुझे मामले की insensitiveखोज करने की आवश्यकता है , और दूसरे में मुझे इसकी आवश्यकता है case sensitive। क्या मुझे केवल प्रदर्शन की दस्तक लेनी है और 'tolower ()' का उपयोग करना है?
Zapnologica

12

यहाँ स्वीकार किए गए उत्तर में इस तथ्य का उल्लेख नहीं है कि यदि आपके पास एक अशक्त स्ट्रिंग टोलवर () है, तो एक अपवाद फेंक देंगे। सुरक्षित तरीका यह करना होगा:

fi => (fi.DESCRIPTION ?? string.Empty).ToLower().Contains((description ?? string.Empty).ToLower())

आप SQL पर अनुवादित क्वेरी पर अपवाद नहीं कर सकते
एलेक्स ज़ुकोवस्क्य

@AlexZhukovskiy यह समस्या के लिए भी प्रासंगिक कैसे है? यदि Fi.DESCRIPTION शून्य है या वर्णन शून्य है तो आपको C # शून्य संदर्भ अपवाद मिल रहा है। यह मायने नहीं रखता है कि LINQ क्वेरी SQL साइड पर क्या रूपांतरित करती है। यहाँ प्रमाण है: dotnetfiddle.net/5pZ1dY
Marko

क्योंकि यह क्वेरी SQL में अनुवाद में विफल हो जाएगी क्योंकि यह शून्य कोयला संचालन ऑपरेटर का समर्थन नहीं करता है। और आप शायद क्लाइंट साइड पर नल कोलशेडिंग का उपयोग करने के लिए सभी प्रविष्टियों को लोड करने के बजाय डेटाबेस को क्वेर कर रहे हैं। इसलिए यदि आप इसका उपयोग करते हैं - यह क्लाइंट की तरफ ठीक है, लेकिन DB पर विफल रहता है, अन्यथा आप DB के साथ ठीक हैं और आप क्लाइंट पक्ष पर nullref की परवाह नहीं करते हैं क्योंकि ऐसा नहीं होगा क्योंकि C # इस क्वेरी और doesn को निष्पादित नहीं करता है 'वास्तव में अशक्त वस्तुओं को नहीं पढ़ा।
एलेक्स

इस जवाब ने मुझे एक समस्या को हल करने में मदद की जो मुझे LINQ पर एंटिटीज में मिल रही थी जहाँ मैं कर रहा था। IndexOf और। एक IEnumerable पर रहता है जहाँ स्ट्रिंग मान डेटाबेस से आ रहा था। जब तक परिणाम की गणना नहीं हो जाती, तब तक मुझे त्रुटि नहीं मिली और फिर मुझे एक त्रुटि संदेश मिला कि "ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट के सेट पर नहीं है।" मैं यह पता नहीं लगा सका कि जब तक मैंने यह पद नहीं देखा था तब तक यह क्यों हो रहा था। धन्यवाद!
19

7

LINQ के लिए, वस्तुओं के लिए C # 6.0 (जो अभिव्यक्ति शारीरिक कार्यों और अशक्त प्रचार की अनुमति देता है) का उपयोग करते हुए, इसे इस तरह एक पंक्ति में भी किया जा सकता है (नल के लिए जाँच)

public static bool ContainsInsensitive(this string str, string value) => str?.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0;

यह काम नहीं कर रहा है क्योंकि ContainsInsensitive एक स्टोर कमांड नहीं है
स्वेन

@Sven - हाँ, यह केवल LINQ ऑब्जेक्ट्स के लिए काम करता है। मैंने अपना जवाब तय कर दिया है। धन्यवाद।
अलेक्सई


3

आप string.Compare का उपयोग कर सकते हैं

    lst.Where(x => string.Compare(x,"valueToCompare",StringComparison.InvariantCultureIgnoreCase)==0);

यदि आप जांच करना चाहते हैं तो "Any" का उपयोग करें

  lst.Any(x => string.Compare(x,"valueToCompare",StringComparison.InvariantCultureIgnoreCase)==0)

इस सवाल का जवाब नहीं है। ओपी एक स्ट्रिंग (यानी, एक स्ट्रिंग में दूसरा होता है) के भीतर 'कॉन्टेन्स' के बारे में पूछ रहा है , न कि स्ट्रिंग्स के संग्रह में एक एकल स्ट्रिंग है।
andrewf

1
public static bool Contains(this string input, string findMe, StringComparison comparisonType)
{
    return String.IsNullOrWhiteSpace(input) ? false : input.IndexOf(findMe, comparisonType) > -1;
}

2
हम linq प्रश्नों में कस्टम एक्सटेंशन विधियों का उपयोग कर सकते हैं? क्या आपको यकीन है ?
विशाल शर्मा


0

ईमानदारी से, यह मुश्किल होने की जरूरत नहीं है। ऐसा लगता है कि शुरुआत में हो सकता है, लेकिन ऐसा नहीं है। यहाँ C # में एक साधारण linq क्वेरी है जो कि अनुरोध के अनुसार है।

मेरे उदाहरण में, मैं उन व्यक्तियों की सूची के खिलाफ काम कर रहा हूं जिनके पास FirstName नामक एक संपत्ति है।

var results = ClientsRepository().Where(c => c.FirstName.ToLower().Contains(searchText.ToLower())).ToList();

यह लोअर केस सर्च पर डेटाबेस सर्च करेगा लेकिन फुल केस रिजल्ट लौटाएगा।


-2

स्ट्रिंग विधि का उपयोग करें

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
           .Where(fi => fi.DESCRIPTION
           .Equals(description, StringComparison.OrdinalIgnoreCase));
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.