यह LINQ एंटिटीज में केस-संवेदी तुलना नहीं है:
Thingies.First(t => t.Name == "ThingamaBob");
मैं LINQ से Entities तक केस की संवेदनशील तुलना कैसे कर सकता हूं?
यह LINQ एंटिटीज में केस-संवेदी तुलना नहीं है:
Thingies.First(t => t.Name == "ThingamaBob");
मैं LINQ से Entities तक केस की संवेदनशील तुलना कैसे कर सकता हूं?
जवाबों:
ऐसा इसलिए है क्योंकि आप LINQ To Entities का उपयोग कर रहे हैं जो अंततः आपके लैंबडा एक्सप्रेशन को SQL स्टेटमेंट में बदल देती है। इसका मतलब है कि केस सेंसिटिविटी आपके SQL सर्वर की दया पर है जो डिफ़ॉल्ट रूप से SQL_Latin1_General_CP1_CI_AS Collation है और यह केस सेंसिटिव नहीं है।
वास्तव में SQL सर्वर पर प्रस्तुत की गई उत्पन्न SQL क्वेरी को देखने के लिए ObjectQuery.ToTraceString का उपयोग करना रहस्य को प्रकट करता है:
string sqlQuery = ((ObjectQuery)context.Thingies
.Where(t => t.Name == "ThingamaBob")).ToTraceString();
जब आप LINQ को Entities क्वेरी के लिए बनाते हैं , तो LINQ से एंटिटीज LINQ parser को क्वेरी को संसाधित करने के लिए लाभ देता है और इसे LINQ अभिव्यक्ति ट्री में परिवर्तित करता है। LINQ एक्सप्रेशन ट्री को तब Object Services API में पास किया जाता है, जो एक्सप्रेशन ट्री को कमांड ट्री में परिवर्तित करता है। फिर इसे स्टोर प्रदाता (जैसे SqlClient) को भेजा जाता है, जो कमांड ट्री को मूल डेटाबेस कमांड टेक्स्ट में बदल देता है। डेटा संग्रह पर निष्पादित हो क्वेरी और परिणाम कर रहे हैं materialized में इकाई ऑब्जेक्ट्स द्वारा वस्तु सेवाएं। मामले की संवेदनशीलता को ध्यान में रखने के लिए कोई तर्क नहीं दिया गया है। तो कोई बात नहीं जो भी आप अपने विधेय में डालते हैं, यह हमेशा आपके SQL सर्वर द्वारा उसी के समान माना जाएगा जब तक आप उस कॉलम के लिए अपने SQL सर्वर Collates को नहीं बदलते।
इसलिए, सबसे अच्छा समाधान का मिलान को बदलने के लिए किया जाएगा नाम में स्तंभ थिंगी मुक़ाबला करने के लिए तालिका Latin1_General_CS_AS जो मामले अपने एसक्यूएल सर्वर पर इस चलाकर प्रति संवेदनशील है:
ALTER TABLE Thingies
ALTER COLUMN Name VARCHAR(25)
COLLATE Latin1_General_CS_AS
SQL सर्वर Collates के बारे में अधिक जानकारी के लिए, SQL सर्वर कोलाज़ केस सेंसिटिव SQL क्वेरी खोज पर एक नज़र डालें
एकमात्र समाधान जो आप ग्राहक पक्ष पर लागू कर सकते हैं, वह है LINQ का उपयोग करने के लिए ऑब्जेक्ट्स के लिए अभी तक एक और तुलना करना जो बहुत सुरुचिपूर्ण नहीं लगता है:
Thingies.Where(t => t.Name == "ThingamaBob")
.AsEnumerable()
.First(t => t.Name == "ThingamaBob");
आप EF6 + कोड-प्रथम के लिए [CaseSensitive] एनोटेशन जोड़ सकते हैं
इस वर्ग को जोड़ें
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class CaseSensitiveAttribute : Attribute
{
public CaseSensitiveAttribute()
{
IsEnabled = true;
}
public bool IsEnabled { get; set; }
}
public class CustomSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(AlterColumnOperation alterColumnOperation)
{
base.Generate(alterColumnOperation);
AnnotationValues values;
if (alterColumnOperation.Column.Annotations.TryGetValue("CaseSensitive", out values))
{
if (values.NewValue != null && values.NewValue.ToString() == "True")
{
using (var writer = Writer())
{
//if (System.Diagnostics.Debugger.IsAttached == false) System.Diagnostics.Debugger.Launch();
// https://github.com/mono/entityframework/blob/master/src/EntityFramework.SqlServer/SqlServerMigrationSqlGenerator.cs
var columnSQL = BuildColumnType(alterColumnOperation.Column); //[nvarchar](100)
writer.WriteLine(
"ALTER TABLE {0} ALTER COLUMN {1} {2} COLLATE SQL_Latin1_General_CP1_CS_AS {3}",
alterColumnOperation.Table,
alterColumnOperation.Column.Name,
columnSQL,
alterColumnOperation.Column.IsNullable.HasValue == false || alterColumnOperation.Column.IsNullable.Value == true ? " NULL" : "NOT NULL" //todo not tested for DefaultValue
);
Statement(writer);
}
}
}
}
}
public class CustomApplicationDbConfiguration : DbConfiguration
{
public CustomApplicationDbConfiguration()
{
SetMigrationSqlGenerator(
SqlProviderServices.ProviderInvariantName,
() => new CustomSqlServerMigrationSqlGenerator());
}
}
अपना DbContext संशोधित करें, जोड़ें
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<CaseSensitiveAttribute, bool>(
"CaseSensitive",
(property, attributes) => attributes.Single().IsEnabled));
base.OnModelCreating(modelBuilder);
}
फिर करो
ऐड-माइग्रेशन केससेन्सिटिव
डेटाबेस अद्यतन करें
https://milinaudara.wordpress.com/2015/02/04/case-sensitive-search-using-entity-framework-with-custom-annotation/ पर लेख के आधार पर कुछ बग ठीक करें
WHERE
SQL सर्वर में स्थितियाँ डिफ़ॉल्ट रूप से असंवेदनशील होती हैं। कॉलम के डिफ़ॉल्ट कोलाज़ ( SQL_Latin1_General_CP1_CI_AS
) को बदलकर इसे संवेदनशील बनाएं SQL_Latin1_General_CP1_CS_AS
।
ऐसा करने का नाजुक तरीका कोड के साथ है। एक नई माइग्रेशन फ़ाइल जोड़ें और फिर इसे Up
विधि के अंदर जोड़ें :
public override void Up()
{
Sql("ALTER TABLE Thingies ALTER COLUMN Name VARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL");
}
परंतु
आप नई EF6 सुविधाओं का उपयोग करके "CaseSensitive" नामक कस्टम एनोटेशन बना सकते हैं और आप अपने गुणों को इस तरह से सजा सकते हैं:
[CaseSensitive]
public string Name { get; set; }
यह ब्लॉग पोस्ट बताता है कि यह कैसे करना है।
@Morteza Manavi द्वारा दिया गया उत्तर समस्या को हल करता है। फिर भी, क्लाइंट-साइड समाधान के लिए , एक सुरुचिपूर्ण तरीका निम्नलिखित होगा (एक डबल चेक जोड़कर)।
var firstCheck = Thingies.Where(t => t.Name == "ThingamaBob")
.FirstOrDefault();
var doubleCheck = (firstCheck?.Name == model.Name) ? Thingies : null;
मुझे मोर्टेजा का उत्तर पसंद आया, और सामान्य रूप से सर्वर साइड पर ठीक करना पसंद करेंगे। क्लाइंट-साइड के लिए मैं आमतौर पर उपयोग करता हूं:
Dim bLogin As Boolean = False
Dim oUser As User = (From c In db.Users Where c.Username = UserName AndAlso c.Password = Password Select c).SingleOrDefault()
If oUser IsNot Nothing Then
If oUser.Password = Password Then
bLogin = True
End If
End If
मूल रूप से, पहले यह जांचना कि यदि आवश्यक मानदंडों वाला कोई उपयोगकर्ता है, तो जांचें कि क्या पासवर्ड समान है। थोड़ा लंबा-घुमावदार, लेकिन मुझे लगता है कि यह पढ़ना आसान है जब मानदंडों का एक पूरा गुच्छा हो सकता है।
न ही StringComparison.IgnoreCase
मेरे लिए काम किया। लेकिन यह किया:
context.MyEntities.Where(p => p.Email.ToUpper().Equals(muser.Email.ToUpper()));
How can I achieve case sensitive comparison
स्ट्रिंग का उपयोग करें
Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCulture);
इसके अलावा, आपको अशक्त के बारे में चिंता करने की ज़रूरत नहीं है और केवल वही जानकारी प्राप्त करें जो आप चाहते हैं।
केस असंवेदनशील के लिए StringComparision.CurrentCultureIgnoreCase का उपयोग करें।
Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCultureIgnoreCase);
EF4 के बारे में निश्चित नहीं है, लेकिन EF5 इसका समर्थन करता है:
Thingies
.First(t => t.Name.Equals(
"ThingamaBob",
System.StringComparison.InvariantCultureIgnoreCase)
StringComparison
एनम को फर्क नहीं पड़ा। मैंने देखा है कि काफी लोग इस तरह का सुझाव देते हुए सोचते हैं कि समस्या ईडीएमएक्स फाइल (डीबी-फर्स्ट) में कहीं होनी चाहिए, हालाँकि stackoverflow.com/questions/841226/…