programing

대소문자를 구분하지 않는 문자열을 LINQ-SQL로 비교

newsource 2023. 5. 15. 21:56

대소문자를 구분하지 않는 문자열을 LINQ-SQL로 비교

ToUpper와 ToLower를 사용하여 대소문자를 구분하지 않는 문자열을 비교하는 것은 현명하지 않다고 읽었지만 LINQ-to-SQL에 관해서는 대안이 없습니다.문자열의 ignoreCase 및 CompareOptions 인수입니다.비교는 LINQ-to-SQL에서 무시됩니다. 대소문자를 구분하는 데이터베이스를 사용하는 경우 대소문자를 구분하지 않는 비교를 요청하더라도 대소문자를 구분하는 비교를 얻을 수 있습니다.ToLower 또는 ToUpper 중 어느 것이 가장 좋은 옵션입니까?하나가 다른 하나보다 나은가요?어디선가 ToUpper가 더 낫다는 글을 읽었다고 생각했는데, 여기에도 해당되는지 모르겠습니다. (코드리뷰를 많이 하고 있고 모두 ToLower를 사용하고 있습니다.)

Dim s = From row In context.Table Where String.Compare(row.Name, "test", StringComparison.InvariantCultureIgnoreCase) = 0

이는 행을 단순히 비교하는 SQL 쿼리로 해석됩니다."test"로 이름을 지정하고 대소문자를 구분하는 데이터베이스에서 "Test" 및 "TEST"를 반환하지 않습니다.

말씀하신 것처럼 ToUpper와 ToLower 사이에는 몇 가지 중요한 차이점이 있으며 대소문자를 구분하지 않는 동등성 검사를 수행할 때 신뢰할 수 있는 정확한 것은 하나뿐입니다.

이상적으로 대소문자를 구분하지 않는 동일성 검사를 수행하는 가장 좋은 방법은 다음과 같습니다.

String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)

그러나 이 경우에는 작동하지 않습니다!그러므로 우리는 계속해서ToUpper또는ToLower.

보안이 안전하도록 Ordinal Ignore Case를 기록합니다.그러나 대/소문자를 구분하는 검사의 정확한 유형은 용도에 따라 다릅니다.그러나 일반적으로 정렬할 때 동일성 검사 및 비교에는 동등성을 사용하고 작업에 적합한 문자열 비교를 선택합니다.

마이클 캐플런(이와 같은 문화 및 캐릭터 처리에 대한 공인된 권위자)은 TopUpper vs.아래쪽:

그는 "끈"이라고 말합니다.To Upper – To Lower 대신 To Upper를 사용하고, OS 케이싱 규칙을 선택하기 위해 불변 문화를 지정합니다."

저는 용한사를 요.System.Data.Linq.SqlClient.SqlMethods.Like(row.Name, "test")내가 보기에는

대소문자를 구분하지 않는 비교를 수행합니다.

EF Core 문서에 따르면, 사례 비감각성 비교의 즉각적인 번역을 제공하지 않기로 한 결정은 설계에 의한 것으로, DB 인덱스가 사용되지 않기 때문에 성능 문제가 대부분입니다.

.은 의 를 제공합니다NET은 오버로드를 제공합니다.string.EqualsStringComparisonenum - 대/소문자 구분 및 비교를 위한 문화를 지정할 수 있습니다.설계상 EF Core는 이러한 오버로드를 SQL로 변환하지 않으며 이러한 오버로드를 사용하려고 하면 예외가 발생합니다.한 가지 예로, EF Core는 대소문자를 구분하거나 대소문자를 구분하지 않는 조합을 사용해야 하는지 알지 못합니다.더 중요한 것은 대부분의 경우 데이터 정렬을 적용하면 인덱스 사용이 방지되어 매우 기본적이고 일반적으로 사용되는 경우 성능에 상당한 영향을 미친다는 점입니다.NET 구성.

즉, EF Core 5.0부터는 쿼리별로 정렬을 지정할 수 있으며, 이를 사용하여 대소문자를 구분하지 않는 비교를 수행할 수 있습니다.

Dim s = From row In context.Table 
        Where EF.Functions.Collate(row.Name, "SQL_Latin1_General_CP1_CI_AS") == "test"

및 C#에서

var s = context.Table
   .Where(row => EF.Functions.Collate(row.Name, "SQL_Latin1_General_CP1_CI_AS") == "test")

.NET 코어를 사용하는 경우, 시스템.데이터. 링크.SqlClient.SqlMethods를 사용할 수 없습니다. 대신 이 방법을 사용하십시오.

EF.Functions.Like(row.Name, "test")

대소문자를 구분하지 않는 문자열을 LINQ-to-SQL로 전달하면 변경되지 않고 SQL로 전달되며 비교가 데이터베이스에서 수행됩니다.데이터베이스에서 대/소문자를 구분하지 않는 문자열 비교를 수행하려면 비교를 수행하는 람다 식을 만들기만 하면 LINQ-to-SQL 공급자가 해당 식을 그대로 SQL 쿼리로 변환합니다.

예를 들어, 이 LINQ 쿼리는 다음과 같습니다.

from user in Users
where user.Email == "foo@bar.com"
select user

LINQ-to-SQL 공급자가 다음 SQL로 변환합니다.

SELECT [t0].[Email]
FROM [User] AS [t0]
WHERE [t0].[Email] = @p0
-- note that "@p0" is defined as nvarchar(11)
-- and is passed my value of "foo@bar.com"

보시다시피, 문자열 매개 변수는 SQL에서 비교됩니다. 즉, 원하는 방식으로 작동해야 합니다.

대/소문자를 구분하는 Linq to Sql 쿼리를 수행하려면 다음 중 하나를 사용하여 서버 데이터 유형을 지정하여 'string' 필드를 대/소문자를 구분하도록 선언합니다.

varchar(4000) COLLATE SQL_Latin1_General_CP1_CS_AS 

또는

nvarchar(Max) COLLATE SQL_Latin1_General_CP1_CS_AS

참고: 위의 조합 유형에서 'CS'는 '대소문자 구분'을 의미합니다.

Visual Studio DBML Designer를 사용하여 정보를 볼 때 "서버 데이터 유형" 필드에 입력할 수 있습니다.

자세한 내용은 http://yourdotnetdesignteam.blogspot.com/2010/06/case-sensitive-linq-to-sql-queries.html 를 참조하십시오.

람다 표현을 사용해서 시도해봤는데 효과가 있었습니다.

List<MyList>.Any (x => (String.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)) && (x.Type == qbType) );

where row.name.StartsWith(q, true, System.Globalization.CultureInfo.CurrentCulture)

다음의 2단계 접근 방식은 저에게 적합합니다(VS2010, ASP).NET MVC3, SQL Server 2008, SQL로 연결):

result = entRepos.FindAllEntities()
    .Where(e => e.EntitySearchText.Contains(item));

if (caseSensitive)
{
    result = result
        .Where(e => e.EntitySearchText.IndexOf(item, System.StringComparison.CurrentCulture) >= 0);
}

데이터베이스에 저장된 값에 공백이 포함될 수 있으므로 이 값을 실행하지 못할 수 있습니다.

String.Equals(row.Name, "test", StringComparison.OrdinalIgnoreCase)

이 문제의 해결책은 공간을 제거한 후 케이스를 변환한 후 다음과 같이 선택하는 것입니다.

 return db.UsersTBs.Where(x => x.title.ToString().ToLower().Replace(" ",string.Empty).Equals(customname.ToLower())).FirstOrDefault();

이 경우의 참고 사항

사용자 지정 이름은 데이터베이스 값과 일치하는 값입니다.

사용자 TB는 클래스입니다.

제목은 데이터베이스 열입니다.

쿼리가 작동하는지 여부와 효율적으로 작동하는지 여부에는 차이가 있다는 것을 기억하십시오.LINQ 문은 문 대상이 SQL Server인 경우 T-SQL로 변환되므로 생성될 T-SQL에 대해 생각해야 합니다.

문자열 사용.Equals는 SQL Server에서 모든 행을 가져온 다음 에 비교할 가능성이 높습니다.NET, 왜냐하면 그것은 a이기 때문입니다.T-SQL로 변환할 수 없는 NET 식입니다.

즉, 표현식을 사용하면 데이터 액세스가 증가하고 인덱스를 사용할 수 있는 기능이 제거됩니다.그것은 작은 테이블에서 작동할 것이고 당신은 그 차이를 알아차리지 못할 것입니다.큰 테이블에서는 성능이 매우 저하될 수 있습니다.

그것은 LINQ에 존재하는 문제 중 하나입니다. 사람들은 더 이상 자신이 작성한 진술이 어떻게 이행될 것인지에 대해 생각하지 않습니다.

이 경우 T-SQL에서도 식을 사용하지 않고 원하는 작업을 수행할 수 없습니다.따라서 이 작업을 더 효율적으로 수행할 수 없습니다.위에 제공된 T-SQL 응답(데이터 정렬과 함께 변수 사용)에서도 인덱스가 무시될 가능성이 높지만, 큰 테이블인 경우 문을 실행하고 실행 계획을 검토하여 인덱스가 사용되었는지 확인해 볼 가치가 있습니다.

언급URL : https://stackoverflow.com/questions/841226/case-insensitive-string-compare-in-linq-to-sql