LINQは大文字と小文字を区別しない


174

このコードは大文字と小文字を区別しますが、大文字と小文字を区別しないようにするにはどうすればよいですか?

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

Sjoerdの答えは正しいですが... iを書くときにトルコ語のwith(たとえば)で名前の検索結果を取得したい、またはその逆です。この場合、ToLowerが正しい方法のようです。私が間違っている場合は私を修正してください。トルコ語について
en

@HeNrik-JYeltonのコメントのトルコテストリンクで承認された回答の下で説明されているように、トルコの文化で実行すると、これらの2つのiは異なるため、他のiで名前を見つけることはできません。ToLowerInvariantが必要です。ここのさまざまな答えの下で議論を参照してください。
ToolmakerSteve

これは古い質問ですが、現在のバージョンではEFコア2.0のToLower()は次のように機能します。person.Where(p => p.Name.ToLower()。Contains(myParam.Name.ToLower() )); 私はこれをPostgres DBに対するLinqクエリで使用しています。私は、DBの列照合で大文字と小文字を区別していません。ToLower()を使用しないと、大文字と小文字が区別されることを確認しました。
シェルペペレイラ

回答:


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 to Entitiesでは機能しません。LINQ to Objectsの素晴らしいソリューションです。
Damian Powell

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

49
ジョンスキートはコメントし、関連する質問は、このメソッドは渡しませんトルコのテストを
JYelton 2012年

5
いいえ。ただし、データベースは文字セットと照合順序で機能します。作業をデータベースにプッシュしようとしている場合、文字セットと照合順序についていくつかの仮定をする必要がありますよね?
クリストファースティーブンソン

66
含まれるIEqualityComparer<string>ものは、比較がどのように機能するかを処理するために属性を使用する必要があります。ToLowerとToUpperを使用して等しいかどうかを確認することはお勧めできません。試してみてください:.Contains(description, StringComparer.CurrentCultureIgnoreCase)たとえば
ドリヴァル

19
@Dorivalからのコメントは、このにErrorMessageを与えるとして、仕事をdoesntの: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
Containswith StringComparerはパラメータとして文字列を受信しないため、ビルドエラーになります。IndexOfQueryable、おそらくSQLに変換することができません。個人的には、LINQ to Databaseについて話すとき、この答えは完全に有効であることがわかりました。
Thariq Nugrohotomo 2015

122

LINQクエリがデータベースコンテキストで実行される場合、への呼び出しContains()LIKE演算子にマップされます。

.Where(a => a.Field.Contains("hello")) になりField LIKE '%hello%'ます。LIKEオペレータは、デフォルトで、ケース鈍感であるが、それはによって変更することができる列の照合順序を変更します

LINQクエリが.NETコンテキストで実行される場合、IndexOf()を使用できますが、そのメソッドはLINQ to SQLではサポートされていません。

LINQ to SQL 、CultureInfoをパラメーターとして使用するメソッドサポートしていません。これは、おそらくSQLサーバーが.NETと同じようにカルチャを処理することを保証できないためです。それはので、これは、完全に真実ではないサポートをStartsWith(string, StringComparison)

ただし、LIKELINQ to SQLおよび.NETでの大文字と小文字を区別しない比較で評価されるメソッドをサポートしていないため、一貫した方法で大文字と小文字を区別しないContains()を実行することはできません。


FYI EF 4.3だけがStartsWithをサポートしていません。私が取得:エンティティへのLINQは方法「ブールSTARTSWITH(可能System.String、System.StringComparison)」を認識しない
nakhli

StartWithはLIKE 'hello%'に変換しますか?
Bart Calixto 2014年

clicdataリンクが停止しています。
Adam Parkin

2
LIKE句の生成されたSQLとdbの動作を掘り下げるための多大な努力
Thariq Nugrohotomo

1
EFを使用するときのオプションとは何か、あるコンテキストではケースinsensitive検索を行う必要があり、別のコンテキストではそれを行う必要がありますcase sensitive。パフォーマンスノックを取り、「toLower()」を使用する必要がありますか?
Zapnologica

12

ここで受け入れられた回答は、null文字列がある場合にToLower()が例外をスローするという事実について言及していません。より安全な方法は次のようにすることです:

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

SQLに変換されたクエリで例外を生成することはできません
Alex Zhukovskiy

@AlexZhukovskiyそれはこの問題にどのように関連していますか?fi.DESCRIPTIONがnullまたはdescriptionがnullの場合、C#null参照例外が発生します。LINQクエリがSQL側で何に変換されるかは関係ありません。これが証明です:dotnetfiddle.net/5pZ1dY
Marko

このクエリは、null合体演算子をサポートしていないため、SQLへの変換に失敗します。そして、クライアント側でnullコアレッシングを使用するためにすべてのエントリをロードする代わりに、データベースをクエリする可能性があります。したがって、使用する場合-クライアント側では問題ありませんが、DBでは失敗します。それ以外の場合は、DBで問題はなく、C#がこのクエリを実行せず、クライアント側でnullrefが発生しないため、このクエリは実行されません。 nullオブジェクトを実際に読み取ることはありません。
Alex Zhukovskiy 2017年

この回答は、データベースから取得した文字列値がnullであるIEnumerableで.IndexOfおよび.Containsを実行していたLINQ to Entitiesで発生していた問題を解決するのに役立ちました。結果が列挙されるまでエラーが発生せず、「オブジェクト参照がオブジェクトのインスタンスに設定されていません」というエラーメッセージが表示されました。この投稿を見るまで、なぜそれが起こっているのか理解できませんでした。ありがとう!
randyh22 '20 / 12/18

7

LINQ to ObjectsのC#6.0(式のボディ関数とnullの伝達を可能にする)を使用すると、次のように1行で実行できます(nullもチェックします)。

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

ContainsInsensitiveはストアコマンドではないため、機能しません
Sven

@Sven-はい、LINQ to Objectsでのみ機能します。答えを直しました。ありがとう。
Alexei

4

この場合、IndexOfが最適です。

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

3

stringを使用できます。

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

含むだけを確認したい場合は、「Any」を使用します

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

これは質問の答えにはなりません。OPは、文字列のコレクションに単一の文字列が含まれているかどうかではなく、文字列内の「含む」(つまり、1つの文字列に別の文字列が含まれる)について尋ねています。
アンドリューフ

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

2
linqクエリでカスタム拡張メソッドを使用できますか?本気ですか ?
Vishal Sharma


0

正直なところ、これは難しいことではありません。最初はそう思われるかもしれませんが、そうではありません。以下は、要求どおりに機能するC#の単純なlinqクエリです。

私の例では、FirstNameと呼ばれる1つのプロパティを持つ人物のリストに対して作業しています。

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

これは、小文字検索でデータベースを検索しますが、完全なケース結果を返します。


-2

String.Equalsメソッドを使用

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
           .Where(fi => fi.DESCRIPTION
           .Equals(description, StringComparison.OrdinalIgnoreCase));
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.