LINQ Büyük / Küçük Harfe Duyarsız


174

Bu kod büyük / küçük harfe duyarlıdır, büyük / küçük harfe duyarsız hale nasıl getirilir?

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

Sjoerd'ın cevapları doğru ama ... i yazarken türkçe i ile isimler için arama sonuçları almak istiyorum (tam tersi). Bu durumda ToLower doğru yol gibi görünüyor. Yanılıyorsam lütfen beni düzeltin. Türk İ hakkında: en.wikipedia.org/wiki/Dotted_and_dotless_I
He Nrik

@HeNrik - Türkiye'de tartışıldığı gibi, JYelton'un kabul edilen cevap altındaki yorumunda test bağlantısı, Türk kültürüyle koştuğunda, bu iki i farklı olacaktır - böylece diğer i ile isimler bulamazsınız. ToLowerInvariant'ı istiyorsunuz. Çeşitli cevaplar altındaki tartışmaya buradan bakın .
ToolmakerSteve

bu eski bir sorudur, ancak mevcut sürümde EF core 2.0 ToLower () 'ın person.Where (p => p.Name.ToLower () gibi çalıştığını belirtmek gerekir. )); Bu bir Postgres DB karşı Linq sorguda kullanıyorum. DB sütun harmanlama büyük / küçük harfe duyarsız değilim ve ben ToLower () olmadan maç açıkça büyük / küçük harf duyarlı olduğunu kontrol ettim.
shelbypereira

Yanıtlar:


72

Burada dizelerle çalıştığımızı varsayarsak, burada başka bir "zarif" çözüm kullanılıyor IndexOf().

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

7
Güzel. Kendi amaçlarım için bu LINQ to Entities için işe yaramıyor. Nesneler LINQ için güzel bir çözüm.
Damian Powell

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

49
Jon Skeet'in ilgili bir soru üzerine yorumladığı gibi , bu yöntem Türkiye Testini geçmeyecektir .
JYelton

5
Hayır, ancak veritabanları karakter kümeleri ve harmanlamadan çıkar. İşi veritabanına aktarmaya çalışıyorsanız, karakter kümesi ve harmanlama hakkında bazı varsayımlar yapmanız gerekir, değil mi?
Christopher Stevenson

66
İçerik IEqualityComparer<string>, karşılaştırmanın nasıl çalışacağını işlemek için öznitelik kullanıyor olmalıdır . Eşitliği kontrol etmek için ToLower ve ToUpper'ı kullanmak kötü bir fikirdir. Deneyin: .Contains(description, StringComparer.CurrentCultureIgnoreCase)örneğin
Dorival

19
@Dorival'dan gelen yorum bu hata 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
mesajını

6
Containsile StringComparerparametre olarak dize almaz, bu nedenle derleme hatası olur. IndexOfüzerinde Queryablemuhtemelen SQL tercüme edilemez. Şahsen ben veritabanına LINQ hakkında konuşurken biz bu cevabın tamamen geçerli bulundu.
Thariq Nugrohotomo

122

LINQ sorgusu veritabanı bağlamında yürütülürse Contains(), LIKEişleç için bir çağrı eşlenir :

.Where(a => a.Field.Contains("hello")) olur Field LIKE '%hello%'. LIKEOperatör varsayılan olarak duyarsız olduğu, ancak bu değiştirilebilir sütunun harmanlama değiştirme .

LINQ sorgusu .NET bağlamında yürütülürse, IndexOf () kullanabilirsiniz , ancak bu yöntem LINQ to SQL'de desteklenmez.

LINQ to SQL , büyük olasılıkla SQL sunucusunun kültürleri .NET ile aynı şekilde işlediğini garanti edemediğinden, parametre olarak bir CultureInfo alan yöntemleri desteklemez . Çünkü bu tamamen doğru değildir does desteği StartsWith(string, StringComparison).

Bununla birlikte, LIKELINQ to SQL'de değerlendirilen bir yöntemi ve .NET'te büyük / küçük harfe duyarlı olmayan bir karşılaştırmayı desteklediği görülmemektedir, bu da büyük / küçük harfe duyarsız Contains () işlevini tutarlı bir şekilde yapmayı imkansız hale getirmektedir.


Sadece FYI EF 4.3, StartsWith'i desteklemez. Ben: Varlıklar LINQ 'Boolean StartsWith (System.String, System.StringComparison)' yöntemini tanımıyor
nakhli

StartWith 'merhaba%' LIKE dönüştürür?
Bart Calixto

Clicdata bağlantısı öldü.
Adam Parkin

2
yan tümcesi için oluşturulan SQL ve db davranışı kazma büyük çaba
Thariq Nugrohotomo

1
EF kullanırken olanlar seçenekleri nedir, Bir bağlamda vaka insensitivearaması yapmam gerekiyor, diğeri de olması gerekiyor case sensitive. Sadece performans çalmamı ve 'toLower ()' kullanmam gerekiyor mu?
Zapnologica

12

Burada kabul edilen cevap, boş bir dizginiz varsa ToLower () 'in bir istisna atacağı gerçeğinden bahsetmez. Daha güvenli bir yol:

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

SQL'e çevrilmiş bir sorguda bir istisna oluşturamazsınız
Alex Zhukovskiy

@AlexZhukovskiy Bu sorunla nasıl alakalı? Fi.DESCRIPTION null veya açıklama null ise, C # null başvuru istisnası alırsınız. SQL tarafında LINQ sorgusunun dönüştürdüğü önemli değildir. İşte kanıt: dotnetfiddle.net/5pZ1dY
Marko

Çünkü bu sorgu boş kömür işleme operatörünü desteklemediğinden SQL'e çeviri başarısız olur. Ve muhtemelen istemci tarafında boş kömür atma kullanmak için tüm girdileri yüklemek yerine veritabanını sorguluyorsunuz. Eğer kullanırsanız - istemci tarafında tamam ama DB başarısız, aksi takdirde DB ile tamam ve istemci tarafında nullref umurumda değil çünkü bu olmayacak çünkü C # bu sorgu yürütmez ve yapmaz aslında boş nesneleri okumaz.
Alex Zhukovskiy

Bu yanıt bana veritabanından gelen dize değerinin boş olduğu bir IEnumerable üzerinde yaptığım .IndexOf ve .Conments varlıkları var LINQ alıyorum bir sorunu çözmek yardımcı oldu. Sonuç numaralandırılana kadar hatayı almıyordum ve sonra "Nesne başvurusu bir nesnenin örneğine ayarlanmadı" hata iletisini aldım. Bu yazıyı görene kadar neden olduğunu anlayamadım. Teşekkürler!
randyh22

7

C # 6.0 (ifade gövdeli işlevlere ve null yayılmaya izin verir) kullanarak, LINQ to Objects için, bu gibi tek bir satırda yapılabilir (ayrıca null olup olmadığını denetleme):

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

ContainsInsensitive bir mağaza komutu olmadığı için çalışmıyor
Sven

@Sven - evet, yalnızca LINQ to Objects için çalışır. Cevabımı düzelttim. Teşekkürler.
Alexei

4

IndexOf bu durumda en iyi sonucu verir

return this
   .ObjectContext
   .FACILITY_ITEM
   .Where(fi => fi.DESCRIPTION.IndexOf(description, StringComparison.OrdinalIgnoreCase)>=0);

3

String kullanabilirsiniz.

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

sadece içindeki içeriği kontrol etmek istiyorsanız "Herhangi"

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

Bu soruya cevap vermiyor. OP , bir dize koleksiyonunun tek bir dize içerip içermediğini değil, bir dize içindeki 'İçerir' (örneğin, bir dize diğerini içerir) hakkında soru sorar .
andrewf

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

2
sorgularında özel uzantı yöntemleri kullanabilir miyiz? Emin misiniz ?
Vishal Sharma


0

Dürüst olmak gerekirse, bunun zor olması gerekmez. Başlangıçta görünebilir, ama değil. İşte tam olarak istendiği gibi C # basit bir linq sorgusu.

Örneğimde, FirstName adlı bir özelliği olan kişilerin bir listesi üzerinde çalışıyorum.

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

Bu, veritabanında küçük harf aramada arama yapar ancak tam vaka sonuçlarını döndürür.


-2

String.Equals Yöntemini Kullan

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
           .Where(fi => fi.DESCRIPTION
           .Equals(description, StringComparison.OrdinalIgnoreCase));
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.