केस असंवेदनशील स्ट्रिंग LINQ-to-SQL में तुलना करें


137

मैंने पढ़ा है कि केस-असंवेदनशील स्ट्रिंग तुलना करने के लिए ToUpper और ToLower का उपयोग करना नासमझी है, लेकिन जब LINQ-to-SQL की बात आती है तो मुझे कोई विकल्प नहीं दिखता। String.Compare की उपेक्षा Ignase और तुलना तर्क LINQ-to-SQL द्वारा अनदेखा कर रहे हैं (यदि आप केस-संवेदी डेटाबेस का उपयोग कर रहे हैं, तो आप केस-संवेदी तुलना प्राप्त करने के बावजूद केस-संवेदी तुलना प्राप्त करते हैं)। क्या यहां टोलवर या टौपर सबसे अच्छा विकल्प है? क्या यह दूसरे से बढ़िया है? मुझे लगा कि मैंने कहीं पढ़ा है कि ToUpper बेहतर था, लेकिन मुझे नहीं पता कि क्या यहां लागू होता है। (मैं बहुत सारे कोड समीक्षाएं कर रहा हूं और हर कोई ToLower का उपयोग कर रहा है।)

Dim s = From row In context.Table Where String.Compare(row.Name, "test", StringComparison.InvariantCultureIgnoreCase) = 0

यह एक SQL क्वेरी का अनुवाद करता है जो केवल पंक्ति की तुलना करती है। नाम "परीक्षण" के साथ आता है और केस-संवेदी डेटाबेस पर "टेस्ट" और "टेस्ट" वापस नहीं आएगा।


1
धन्यवाद! इसने आज सच में मेरी गांड को बचा लिया। नोट: यह अन्य LINQ एक्सटेंशन के साथ भी काम करता है जैसे LINQQuery.Contains("VaLuE", StringComparer.CurrentCultureIgnoreCase)और LINQQuery.Except(new string[]{"A VaLUE","AnOTher VaLUE"}, StringComparer.CurrentCultureIgnoreCase)। वाहू!
ग्रेग ब्राई

मजेदार, मैंने अभी-अभी पढ़ा कि टौपर इस स्रोत से तुलना करने में बेहतर था: msdn.microsoft.com/en-us/library/dd465121
malckier

जवाबों:


110

जैसा कि आप कहते हैं, ToUpper और ToLower के बीच कुछ महत्वपूर्ण अंतर हैं, और केवल एक ही निश्चित रूप से सटीक है जब आप केस असंवेदनशील समानता जाँच करने का प्रयास कर रहे हैं।

आदर्श रूप से, केस-असंवेदनशील समानता जांच करने का सबसे अच्छा तरीका होगा :

String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)

ध्यान दें, इस मामले में यह काम नहीं करता है ! इसलिए हम ToUpperया के साथ फंस गए हैं ToLower

सुरक्षा को सुरक्षित बनाने के लिए साधारण इग्नोरकेस पर ध्यान दें । लेकिन वास्तव में आपके द्वारा उपयोग किए जाने वाले संवेदनशील चेक का प्रकार इस बात पर निर्भर करता है कि आपके उद्देश्य क्या हैं। लेकिन सामान्य तौर पर समानता जांच के लिए बराबरी का उपयोग करें और जब आप छँटाई कर रहे हों, तब तुलना करें और फिर नौकरी के लिए सही StringComparison चुनें।

माइकल कपलान (संस्कृति और चरित्र पर एक मान्यताप्राप्त अधिकार जो इस तरह से है) में ToUpper बनाम ToLower पर प्रासंगिक पोस्ट हैं:

वह कहते हैं, "स्ट्रिंग। टॉपर - टावलर के बजाय टौपर का उपयोग करें, और ओएस केसिंग नियमों को लेने के लिए इनवेरिन्टकल्चर निर्दिष्ट करें "


1
ऐसा लगता है कि यह SQL सर्वर पर लागू नहीं होता है: ऊपरी प्रिंट करें ('Große Stra'e') रिटर्न STRAßE
BlueMonkMN

1
इसके अलावा, आपके द्वारा प्रदान किए गए सैंपल कोड में वही समस्या है, जो मैंने कोड-संवेदी होने के कारण प्रदान की थी, जब MS SQL 2005 डेटाबेस पर LINQ-to-SQL के माध्यम से चलाया जाता है।
BlueMonkMN

2
मैं सहमत हूँ। क्षमा करें, मैं स्पष्ट नहीं था। आपके द्वारा प्रदान किया गया नमूना कोड Linq2Sql के साथ काम नहीं करता है जैसा कि आपने अपने मूल प्रश्न में बताया है। मैं केवल यह कहकर आराम कर रहा था कि आपके द्वारा शुरू किया गया रास्ता जाने का एक शानदार तरीका है - अगर यह केवल इस परिदृश्य में काम करता है। और हां, एक और माइक कपलान साबुनबॉक्स है जो SQL सर्वर के चरित्र को संभालने के लिए सभी जगह है। यदि आपको केस असंवेदनशील चाहिए और इसे किसी अन्य तरीके से प्राप्त नहीं किया जा सकता है, तो मैं सुझाव दे रहा था (अस्पष्ट रूप से) कि आप डेटा को अपरकेस के रूप में संग्रहीत करते हैं, और फिर इसे अपरकेस के रूप में क्वेरी करते हैं।
एंड्रयू अरनोट

3
यदि आपके पास एक मामला संवेदनशील डेटाबेस है, और आप मिश्रित मामले में स्टोर करते हैं और ऊपरी मामले में खोज करते हैं, तो आपको मैच नहीं मिलेंगे। यदि आप अपनी खोज में डेटा और क्वेरी दोनों को ऊपर चढ़ाते हैं, तो आप अपने द्वारा खोजे जा रहे सभी पाठ को प्रत्येक क्वेरी के लिए परिवर्तित कर रहे हैं, जो प्रदर्शन योग्य नहीं है।
एंड्रयू अरनोट

1
@BlueMonkMN, क्या आप सुनिश्चित हैं कि आपने सही स्निपेट चिपकाए हैं? यह मानना ​​मुश्किल है कि MSSQL सर्वर रेड को ब्लैक से अधिक पसंद करता है।
ग्रीनल्डमैन

75

मैंने System.Data.Linq.SqlClient.SqlMethods.Like(row.Name, "test") अपनी क्वेरी में उपयोग किया ।

यह केस-असंवेदनशील तुलना करता है।


3
हा! कई वर्षों से linq 2 sql का उपयोग किया जा रहा है, लेकिन अब तक SqlMethods को नहीं देखा है, धन्यवाद!
कार्ल हॉबर्ग

3
प्रतिभाशाली! हालांकि अधिक विस्तार का उपयोग कर सकता है। क्या यह लाइक के अपेक्षित उपयोगों में से एक है? क्या ऐसे संभावित इनपुट हैं जो झूठे सकारात्मक परिणाम का कारण बनेंगे? या एक गलत नकारात्मक परिणाम? इस पद्धति पर प्रलेखन की कमी है, जहां प्रलेखन उस तरह की विधि के संचालन का वर्णन करेगा ?
टास्क

2
मुझे लगता है कि यह सिर्फ इस बात पर निर्भर करता है कि SQL सर्वर स्ट्रिंग्स की तुलना कैसे करता है, जो संभवत: कहीं न कहीं विन्यास योग्य है।
एंड्रयू डेवी

11
System.Data.Linq.SqlClient.SqlMethods.Like (row.Name, "test") row.Name.Contains ("परीक्षण") के समान ही है। जैसा कि एंड्रयू कह रहा है, यह sql सर्वर के टकराव पर निर्भर करता है। तो लाइक (या होता है) हमेशा केस-असंवेदनशील तुलना नहीं करता है।
डॉकमैन

3
ज्ञात हो, यह कोड को भी युगल बनाता है SqlClient
जैदर

5

मैंने लैंबडा अभिव्यक्ति का उपयोग करके यह कोशिश की, और इसने काम किया।

List<MyList>.Any (x => (String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) && (x.Type == qbType) );


18
ऐसा इसलिए है क्योंकि आप एक का उपयोग कर रहे हैं List<>, जिसका अर्थ है कि तुलना में IQueryable(या ObjectQuery) के बजाय इन-मेमोरी (C # कोड) होता है जो डेटाबेस में तुलना का प्रदर्शन करेगा ।
drzaus

1
@Drzaus ने क्या कहा। यह जवाब गलत है, यह देखते हुए कि संदर्भ linq2sql है, और नियमित रूप से linq नहीं है।
रासना

0

यदि आप एक स्ट्रिंग पास करते हैं जो LINQ-to-SQL में केस-असंवेदनशील है, तो यह SQL अपरिवर्तित हो जाएगा और तुलना डेटाबेस में होगी। यदि आप डेटाबेस में केस-असंवेदनशील स्ट्रिंग तुलना करना चाहते हैं, तो आपको केवल एक लैम्ब्डा अभिव्यक्ति बनाने की आवश्यकता है जो तुलना करता है और LINQ-to-SQL प्रदाता उस स्ट्रिंग को अपने स्ट्रिंग के साथ SQL क्वेरी में अनुवाद करेगा।

उदाहरण के लिए इस LINQ क्वेरी:

from user in Users
where user.Email == "foo@bar.com"
select user

LINQ-to-SQL प्रदाता द्वारा निम्न एसक्यूएल में अनुवाद किया जाता है:

SELECT [t0].[Email]
FROM [User] AS [t0]
WHERE [t0].[Email] = @p0
-- note that "@p0" is defined as nvarchar(11)
-- and is passed my value of "foo@bar.com"

जैसा कि आप देख सकते हैं, स्ट्रिंग पैरामीटर की तुलना एसक्यूएल में की जाएगी जिसका अर्थ है कि चीजों को काम करना चाहिए जिस तरह से आप उनसे उम्मीद करेंगे।


मुझे समझ नहीं आ रहा है कि आप क्या कह रहे हैं। 1) स्ट्रिंग्स स्वयं .NET में केस-असंवेदनशील या केस-सेंसिटिव नहीं हो सकते हैं, इसलिए मैं "केस-इन्सेंसिव स्ट्रिंग" पास नहीं कर सकता। 2) एक LINQ क्वेरी मूल रूप से एक लैम्ब्डा अभिव्यक्ति है, और यह है कि मैं अपने दो तार कैसे गुजर रहा हूं, इसलिए यह मेरे लिए कोई मतलब नहीं है।
ब्लूमाँकॉन 18

3
मैं CASE-SENSITIVE डेटाबेस पर CASE-INSENSITIVE तुलना करना चाहता हूं।
BlueMonkMN

क्या मामला-संवेदनशील डेटाबेस आप उपयोग कर रहे हैं?
एंड्रयू हरे

इसके अलावा, एक LINQ क्वेरी एक लैम्ब्डा अभिव्यक्ति नहीं है। LINQ क्वेरी कई हिस्सों (सबसे विशेष रूप से क्वेरी ऑपरेटर्स और लैम्ब्डा एक्सप्रेशन) से बना है।
एंड्रयू हरे

इस जवाब से ब्लूमाँकएमएन टिप्पणियों के रूप में कोई मतलब नहीं है।
अल्फ

0

मामले के प्रति संवेदनशील लाइनक को करने के लिए Sql प्रश्नों में निम्नलिखित में से किसी एक का उपयोग करके सर्वर डेटा प्रकार निर्दिष्ट करके संवेदनशील होने के लिए 'स्ट्रिंग' फ़ील्ड घोषित करें;

varchar(4000) COLLATE SQL_Latin1_General_CP1_CS_AS 

या

nvarchar(Max) COLLATE SQL_Latin1_General_CP1_CS_AS

नोट: उपरोक्त कोलाज प्रकारों में 'CS' का अर्थ 'केस सेंसिटिव' है।

विजुअल स्टूडियो DBML डिज़ाइनर का उपयोग करके किसी प्रॉपर्टी को देखने पर इसे "सर्वर डेटा टाइप" फ़ील्ड में दर्ज किया जा सकता है।

अधिक जानकारी के लिए देखें http://yourdotnetdesignteam.blogspot.com/2010/06/case-sensitive-linq-to-sql-queries.html


वह मुद्दा है। आम तौर पर मैं जिस क्षेत्र का उपयोग करता हूं वह संवेदनशील है (रासायनिक सूत्र सीओ [कार्बन मोनोऑक्साइड] सह [कोबाल्ट] से अलग है)। हालांकि, एक विशिष्ट स्थिति (खोज) में मैं सह और सीओ दोनों से मेल खाना चाहता हूं। एक अलग "सर्वर डेटा प्रकार" के साथ एक अतिरिक्त संपत्ति को परिभाषित करना कानूनी नहीं है (linq to sql केवल एक संपत्ति प्रति वर्ग कॉलम की अनुमति देता है)। तो अभी भी नहीं जाना है।
डॉकमैन

इसके अलावा, यूनिट परीक्षण करते समय, यह दृष्टिकोण डेटा मॉक के साथ कंपैटेबिल नहीं होगा। स्वीकृत उत्तर में linq / lambda दृष्टिकोण का उपयोग करने के लिए सबसे अच्छा है।
डेरिक

0
where row.name.StartsWith(q, true, System.Globalization.CultureInfo.CurrentCulture)

1
SQL टेक्स्ट क्या है जिसमें यह अनुवादित हो जाता है, और क्या यह SQL वातावरण में असंवेदनशील होने की अनुमति देता है जो अन्यथा इसे केस-संवेदी मानते हैं?
BlueMonkMN

0

निम्नलिखित 2-चरण दृष्टिकोण मेरे लिए काम करता है (VS2010, ASP.NET MVC3, SQL Server 2008, Linq to SQL):

result = entRepos.FindAllEntities()
    .Where(e => e.EntitySearchText.Contains(item));

if (caseSensitive)
{
    result = result
        .Where(e => e.EntitySearchText.IndexOf(item, System.StringComparison.CurrentCulture) >= 0);
}

1
इस कोड में एक बग है यदि पाठ खोज पाठ के साथ शुरू होता है (होना चाहिए = = 0)
फ्लैटलाइनर DOA

@FlatlinerDOA यह वास्तव में होना चाहिए != -1क्योंकि IndexOf "रिटर्न -1 अगर चरित्र या स्ट्रिंग नहीं मिली है"
drzaus

0

कभी-कभी डेटाबेस में संग्रहीत मूल्य में रिक्त स्थान हो सकते हैं, इसलिए इसे चलाना विफल हो सकता है

String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)

इस समस्या का समाधान अंतरिक्ष को हटाना है फिर इसके मामले को परिवर्तित करें और फिर इस तरह का चयन करें

 return db.UsersTBs.Where(x => x.title.ToString().ToLower().Replace(" ",string.Empty).Equals(customname.ToLower())).FirstOrDefault();

इस मामले में ध्यान दें

customname डेटाबेस मान के साथ मिलान करने के लिए मूल्य है

UsersTBs वर्ग है

शीर्षक डेटाबेस कॉलम है


-1

याद रखें कि क्वेरी काम करती है और क्या यह कुशलता से काम करती है या नहीं, इसके बीच अंतर है ! LINQ स्टेटमेंट T-SQL में तब बदल जाता है जब स्टेटमेंट का टारगेट SQL Server होता है, इसलिए आपको T-SQL के बारे में सोचने की जरूरत है जो कि उत्पादित होगी।

String.Equals का उपयोग करना सबसे अधिक संभावना है (मैं अनुमान लगा रहा हूं) SQL सर्वर से सभी पंक्तियों को वापस लाता हूं और फिर .NET में तुलना करता हूं, क्योंकि यह एक .NET अभिव्यक्ति है जिसे टी-एसक्यूएल में अनुवाद नहीं किया जा सकता है।

दूसरे शब्दों में एक अभिव्यक्ति का उपयोग करने से आपके डेटा का उपयोग बढ़ेगा और इंडेक्स का उपयोग करने की आपकी क्षमता को हटा देगा। यह छोटे तालिकाओं पर काम करेगा और आप अंतर पर ध्यान नहीं देंगे। एक बड़ी मेज पर यह बहुत खराब प्रदर्शन कर सकता है।

LINQ के साथ मौजूद समस्याओं में से एक है; लोग अब इस बारे में नहीं सोचते हैं कि वे जो बयान लिखते हैं वह कैसे पूरा होगा।

इस मामले में एक अभिव्यक्ति का उपयोग किए बिना आप क्या करना चाहते हैं - टी-एसक्यूएल में भी नहीं है। इसलिए आप इसे अधिक कुशलता से करने में सक्षम नहीं हो सकते हैं। यहां तक ​​कि ऊपर दिए गए टी-एसक्यूएल उत्तर (टकराव के साथ चर का उपयोग करते हुए) सबसे अधिक संभावना इंडेक्स में परिणाम होगा, लेकिन अगर यह एक बड़ी तालिका है, तो यह कथन को चलाने और निष्पादन योजना को देखने के लायक है कि क्या सूचकांक का उपयोग किया गया था ।


2
यह सच नहीं है (यह क्लाइंट के लिए पंक्तियों को वापस करने का कारण नहीं बनता है)। मैंने String.Equals का उपयोग किया है और इसका कारण यह नहीं है क्योंकि यह TSQL स्ट्रिंग तुलना में परिवर्तित हो जाता है, जिसका व्यवहार डेटाबेस या सर्वर के टकराव पर निर्भर करता है। मैं एक के लिए कैसे हर LINQ SQL अभिव्यक्ति मैं लिखने TSSQL में परिवर्तित हो जाएगा पर विचार करते हैं। जो मैं चाहता हूं उसका तरीका यह है कि TOUpper का उपयोग करके उत्पन्न TSQL को UPPER का उपयोग करने के लिए मजबूर किया जाए। तब सभी रूपांतरण और तुलना तर्क अभी भी TSQL में किया जाता है ताकि आप अधिक प्रदर्शन न खोएं।
BlueMonkMN
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.