LINQ는 대소 문자를 구분하지 않습니다


174

이 코드는 대소 문자를 구분합니다. 대소 문자를 구분하지 않는 방법은 무엇입니까?

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

Sjoerd의 답변은 정확하지만 ... i를 쓸 때 터키어 İ (예 :)로 이름에 대한 검색 결과를 얻고 싶습니다. 이 경우 ToLower가 올바른 방법으로 보입니다. 내가 틀렸다면 정정 해주세요. 터키어 정보 : en.wikipedia.org/wiki/Dotted_and_dotless_I
그는 Nrik

@HeNrik-터키 문화와 함께 실행할 때 허용되는 답변 아래의 JYelton의 의견에있는 터키 테스트 링크에서 논의한 것처럼, 그 두 가지 i가 다를 수 있으므로 다른 i와 이름을 찾을 수 없습니다. ToLowerInvariant를 원합니다. 다양한 답변 아래 토론을 참조 하십시오 .
ToolmakerSteve

이것은 오래된 질문이지만 현재 버전에서 EF core 2.0 ToLower ()는 다음과 같이 작동합니다. )); Postgres DB에 대한 Linq 쿼리에서 이것을 사용하고 있습니다. DB의 열 데이터 정렬에 대소 문자를 구분하지 않고 ToLower () 없이는 대 / 소문자를 구분하여 일치하는지 확인했습니다.
shelbypereira

답변:


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
Jon Skeet관련 질문 에 대해 언급 한 것처럼 이 방법은 터키 테스트를 통과하지 못합니다 .
JYelton

5
아니요, 그러나 데이터베이스는 문자 집합과 데이터 정렬에서 작동합니다. 작업을 데이터베이스로 푸시하려는 경우 문자 집합 및 데이터 정렬에 대한 몇 가지 가정을해야합니다.
Christopher Stevenson

66
포함은 IEqualityComparer<string>비교 작동 방식을 처리하기 위해 속성을 사용해야합니다 . 평등을 확인하기 위해 ToLower와 ToUpper를 사용하는 것은 나쁜 생각입니다. 시도 : .Contains(description, StringComparer.CurrentCultureIgnoreCase)예를 들어
Dorival

19
@Dorival의 주석은 다음 오류 메시지를 표시하므로 작동하지 않습니다.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

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 Server가 .NET과 동일한 문화권을 처리한다고 보장 할 수 없기 때문일 것입니다. 지원 하지 않기 때문에 이것은 사실이 아닙니다 StartsWith(string, StringComparison).

그러나 LIKELINQ to SQL에서 평가하는 방법 과 .NET에서 대소 문자를 구분하지 않는 비교를 지원하지 않으므로 대소 문자를 구분하지 않는 Contains ()를 일관된 방식으로 수행 할 수 없습니다.


FYI EF 4.3 만 StartsWith를 지원하지 않습니다. LINQ to Entities가 'Boolean StartsWith (System.String, System.StringComparison)'메서드를 인식하지 못함
nakhli

StartWith는 LIKE 'hello %'로 변환됩니까?
Bart Calixto 2016 년

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이 널이거나 description이 널이면 C # 널 참조 예외가 발생합니다. LINQ 쿼리가 SQL 쪽에서 무엇으로 변환되는지는 중요하지 않습니다. 이에 대한 증거는 다음과 같습니다. dotnetfiddle.net/5pZ1dY
Marko

이 쿼리는 null 병합 연산자를 지원하지 않기 때문에 SQL 로의 변환에 실패하기 때문입니다. 그리고 클라이언트 측에서 null 병합을 사용하기 위해 모든 항목을로드하는 대신 데이터베이스를 쿼리하는 것입니다. 따라서 사용하면 클라이언트 쪽에서는 괜찮지 만 DB에서는 실패합니다. 그렇지 않으면 DB에서는 괜찮으며 C # 은이 쿼리를 실행하지 않기 때문에 클라이언트 쪽에서는 nullref를 신경 쓰지 않습니다. 실제로 null 객체를 읽지 않습니다.
Alex Zhukovskiy

이 답변은 내가 .IndexOf와.를하고있는 엔터티에 LINQ를 받고있는 문제를 해결하는 데 도움이되었습니다. 데이터베이스에서 오는 문자열 값이 null 인 IEnumerable에 포함되어 있습니다. 결과가 열거 될 때까지 오류가 발생하지 않았으며 "개체 참조가 개체의 인스턴스로 설정되지 않았습니다"라는 오류 메시지가 나타납니다. 이 게시물을 볼 때까지 왜 발생했는지 알 수 없었습니다. 감사!
randyh22

7

LINQ to Objects에 대해 C # 6.0 (표현식 본문 함수 및 null 전파 허용)을 사용하면 다음과 같이 한 줄로 수행 할 수 있습니다 (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

문자열을 사용할 수 있습니다.

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

포함을 확인하려면 "Any"를 사용하십시오.

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

이것은 질문에 대답하지 않습니다. OP는 문자열 컬렉션에 단일 문자열이 포함되어 있는지 여부가 아니라 문자열 내에 '포함'에 대해 묻습니다 (즉, 한 문자열에 다른 문자열이 포함됨).
andrewf

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이라는 속성이 하나있는 사람 목록에 대해 작업하고 있습니다.

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.