Bu, LINQ to Entities'deki büyük / küçük harfe duyarlı bir karşılaştırma değildir:
Thingies.First(t => t.Name == "ThingamaBob");
LINQ to Entities ile büyük / küçük harfe duyarlı karşılaştırmayı nasıl yapabilirim?
Bu, LINQ to Entities'deki büyük / küçük harfe duyarlı bir karşılaştırma değildir:
Thingies.First(t => t.Name == "ThingamaBob");
LINQ to Entities ile büyük / küçük harfe duyarlı karşılaştırmayı nasıl yapabilirim?
Yanıtlar:
Bunun nedeni , sonuçta Lambda ifadelerinizi SQL ifadelerine dönüştüren LINQ To Entities kullanıyor olmanızdır . Bu, büyük / küçük harf duyarlılığının varsayılan olarak SQL_Latin1_General_CP1_CI_AS Harmanlamasına sahip olan ve büyük / küçük harfe duyarlı OLMAYAN SQL Sunucunuzun insafına kaldığı anlamına gelir .
Aslında SQL Server'a gönderilen oluşturulan SQL sorgusunu görmek için ObjectQuery.ToTraceString kullanmak gizemi ortaya çıkarır:
string sqlQuery = ((ObjectQuery)context.Thingies
.Where(t => t.Name == "ThingamaBob")).ToTraceString();
Bir LINQ to Entities sorgusu oluşturduğunuzda, LINQ to Entities , sorguyu işlemeye başlamak için LINQ ayrıştırıcısını kullanır ve bunu bir LINQ ifade ağacına dönüştürür. LINQ ifade ağacı daha sonra ifade ağacını bir komut ağacına dönüştüren Nesne Hizmetleri API'sine aktarılır . Daha sonra, komut ağacını yerel veritabanı komut metnine dönüştüren mağaza sağlayıcısına (örn. SqlClient) gönderilir. Veri deposu idam olsun sorgulamak ve sonuçları edilir materyalize içine Varlık Nesneleri tarafından Nesne Hizmetleri. Büyük / küçük harf duyarlılığını hesaba katmak için arasına hiçbir mantık konulmadı. Dolayısıyla yükleminize hangi durumu koyarsanız koyun, o sütun için SQL Server Harmanlamanızı değiştirmediğiniz sürece SQL Server tarafından her zaman aynı şekilde davranacaktır.
Bu nedenle, en iyi çözüm , Thingies tablosundaki Ad sütununun harmanlamasını, SQL Server'ınızda bunu çalıştırarak büyük / küçük harfe duyarlı olan COLLATE Latin1_General_CS_AS olarak değiştirmek olacaktır :
ALTER TABLE Thingies
ALTER COLUMN Name VARCHAR(25)
COLLATE Latin1_General_CS_AS
SQL Server Harmanlamaları hakkında daha fazla bilgi için, SQL SUNUCUSU Harmanlama Büyük / Küçük Harfe Duyarlı SQL Sorgu Aramasına bir göz atın
İstemci tarafında uygulayabileceğiniz tek çözüm, çok zarif görünmeyen başka bir karşılaştırma yapmak için LINQ to Objects'i kullanmaktır :
Thingies.Where(t => t.Name == "ThingamaBob")
.AsEnumerable()
.First(t => t.Name == "ThingamaBob");
EF6 + Code-first için [CaseSensitive] ek açıklaması ekleyebilirsiniz
Bu sınıfları ekle
[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'inizi değiştirin, ekleyin
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<CaseSensitiveAttribute, bool>(
"CaseSensitive",
(property, attributes) => attributes.Single().IsEnabled));
base.OnModelCreating(modelBuilder);
}
O zaman yap
Add-Migration CaseSensitive
Veri tabanını güncelle
bazı hata düzeltmeleri ile https://milinaudara.wordpress.com/2015/02/04/case-sensitive-search-using-entity-framework-with-custom-annotation/ makalesine göre
WHERE
SQL Server'daki koşullar varsayılan olarak büyük / küçük harf duyarlıdır. Sütunun varsayılan harmanlamalarını ( SQL_Latin1_General_CP1_CI_AS
) olarak değiştirerek büyük / küçük harfe duyarlı hale getirin SQL_Latin1_General_CP1_CS_AS
.
Bunu yapmanın kırılgan yolu kodlamadır. Yeni bir geçiş dosyası ekleyin ve ardından bunu Up
yöntemin içine ekleyin :
public override void Up()
{
Sql("ALTER TABLE Thingies ALTER COLUMN Name VARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL");
}
Fakat
Yeni EF6 özelliklerini kullanarak "CaseSensitive" adlı özel açıklama oluşturabilir ve özelliklerinizi şu şekilde dekore edebilirsiniz:
[CaseSensitive]
public string Name { get; set; }
Bu blog yazısı bunun nasıl yapılacağını açıklıyor.
@Morteza Manavi'nin verdiği cevap sorunu çözüyor. Yine de, bir istemci tarafı çözümü için , zarif bir yol şu olacaktır (bir çift kontrol eklemek).
var firstCheck = Thingies.Where(t => t.Name == "ThingamaBob")
.FirstOrDefault();
var doubleCheck = (firstCheck?.Name == model.Name) ? Thingies : null;
Morteza'nın cevabını beğendim ve normalde sunucu tarafında düzeltmeyi tercih ederim. İstemci tarafı için normalde kullanıyorum:
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
Temel olarak, önce gerekli kriterlere sahip bir kullanıcı olup olmadığını kontrol edin, ardından şifrenin aynı olup olmadığını kontrol edin. Biraz uzun soluklu, ama bir sürü kriter söz konusu olduğunda okumanın daha kolay olduğunu hissediyorum.
Hiçbiri StringComparison.IgnoreCase
benim için çalışmadı. Ama bu yaptı:
context.MyEntities.Where(p => p.Email.ToUpper().Equals(muser.Email.ToUpper()));
How can I achieve case sensitive comparison
String.Equals kullanın
Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCulture);
Ayrıca, null konusunda endişelenmenize ve yalnızca istediğiniz bilgileri geri almanıza gerek yoktur.
Büyük / Küçük Harfe Duyarsız için StringComparision.CurrentCultureIgnoreCase kullanın.
Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCultureIgnoreCase);
EF4 hakkında emin değilim, ancak EF5 bunu destekliyor:
Thingies
.First(t => t.Name.Equals(
"ThingamaBob",
System.StringComparison.InvariantCultureIgnoreCase)
StringComparison
numaralandırmaların bir fark yaratmasını sağlayamadım . Sorunun EDMX dosyasında (db-ilk) bir yerde olduğunu düşünmek için bu tür bir şeyin işe yaraması gerektiğini öneren yeterince insan gördüm, ancak stackoverflow.com/questions/841226/…