문제

데이터베이스와 C # 코드 사이에 캐싱 레이어를 구현하고 있습니다. 아이디어는 쿼리에 대한 매개 변수를 기반으로 특정 DB 쿼리의 결과를 캐시하는 것입니다. 데이터베이스는 기본 데이터 정렬 (SQL_Latin1_General_CP1_CI_AS 또는 Latin1_General_CI_AS)을 사용하고 있습니다. 일부 간단한 인터넷 검색을 기반으로하는 것은 동등성에 대해 동일하고 정렬에 대해서는 다릅니다.

데이터베이스의 데이터 정렬이 사용하는 것과 같이 적어도 동등성 테스트 및 해시 코드 생성을 위해 동일한 동작을 제공 할 수있는 .NET StringComparer가 필요합니다. 목표는 C # 코드의 .NET 사전에서 StringComparer를 사용하여 특정 문자열 키가 이미 캐시에 있는지 여부를 확인할 수 있도록하는 것입니다.

정말 단순화 된 예 : 라코 디스

StringComparer가 데이터베이스의 데이터 정렬과 일치하는 것이 중요한 이유는 거짓 양성과 거짓 음성이 모두 코드에 나쁜 영향을 미치기 때문입니다.

StringComparer가 데이터베이스가 구별된다고 생각할 때 두 개의 키 A와 B가 동일하다고 말하면 데이터베이스에 두 개의 키가있는 두 개의 행이있을 수 있지만 요청시 캐시는 두 번째 키가 반환되는 것을 방지합니다. A와 B의 연속-get for B가 캐시를 잘못 적중하고 A에 대해 검색된 객체를 반환하기 때문입니다.

데이터베이스가 A와 B가 동일하다고 생각할 때 StringComparer가 A와 B가 다르다고 말하면 문제는 더 미묘하지만 덜 문제가되지는 않습니다. 두 키에 대한 GetObject 호출은 괜찮을 것이며 동일한 데이터베이스 행에 해당하는 개체를 반환합니다. 그러나 키 A로 SaveObject를 호출하면 캐시가 올바르지 않게됩니다. 이전 데이터가있는 키 B에 대한 캐시 항목이 여전히 있습니다. 후속 GetObject (B)는 오래된 정보를 제공합니다. 따라서 내 코드가 올바르게 작동하려면 동등성 테스트 및 해시 코드 생성을위한 데이터베이스 동작과 일치하는 StringComparer가 필요합니다. 지금까지 인터넷 검색을 통해 SQL 데이터 정렬과 .NET 비교가 정확히 동일하지 않다는 사실에 대한 많은 정보를 얻었지만 차이점이 무엇인지, 정렬의 차이로만 제한되는지 또는 찾을 수 있는지 여부에 대한 세부 정보는 없습니다. 범용 솔루션이 필요하지 않은 경우 특정 SQL 데이터 정렬에 해당하는 StringComparer

(참고-캐싱 레이어는 범용이므로 키의 특성과 적절한 데이터 정렬에 대해 특별한 가정을 할 수 없습니다. 데이터베이스의 모든 테이블은 동일한 기본 서버 데이터 정렬을 공유합니다. 존재하는 데이터 정렬과 일치해야 함)

도움이 되었습니까?

해결책

CollationInfo를 살펴보십시오. 클래스. 어디서 얻을 수 있는지는 확실하지 않지만 Microsoft.SqlServer.Management.SqlParser.dll라는 어셈블리에 있습니다. Collations의 정적 목록이 있습니다. (이름) 및 정적 메서드 GetCollationInfo (이름 별 ).

CollationInfo에는 가 있습니다. Comparer . StringComparer와 정확히 동일하지는 않지만 유사한 기능을 가지고 있습니다.

편집 : Microsoft.SqlServer.Management.SqlParser.dll은 SMO (공유 관리 개체) 패키지의 일부입니다. 이 기능은 여기에서 SQL Server 2008 R2 용으로 다운로드 할 수 있습니다.

http://www.microsoft.com/download/ en / details.aspx? id= 16978 # SMO

편집 : CollationInfo에는 EqualityComparer IEqualityComparer<string>입니다.

다른 팁

최근 같은 문제에 직면했습니다. SQL과 유사한 스타일로 작동하는 유전자 태그 코드가 필요합니다. 나는 IEqualityComparer<string>와 그 CollationInfo를 시도했습니다. DB가 항상 _AS (악센트 구분)이면 솔루션이 작동하지만 AI 또는 WI 인 데이터 정렬을 변경하는 경우 솔루션이 작동합니다. 또는 "무감각"한 경우 해싱이 중단됩니다.
왜? Microsoft.SqlServer.Management.SqlParser.dll 을 디 컴파일하고 내부를 살펴보면 EqualityComparer가 내부적으로 CollationInfo (mscorlib.dll의 내부 클래스)를 사용하고 마지막으로 다음을 수행한다는 것을 알 수 있습니다. 라코 디스

보시다시피 "aa"및 "AA"에 대해 동일한 해시 코드를 생성 할 수 있지만 "äå"및 "aa"에 대해서는 동일하지 않습니다 (대부분의 문화권에서 분음 부호 (AI)를 무시하면 동일합니다. 따라서 동일한 해시 코드를 가져야합니다). .NET API가 이것에 의해 제한되는 이유를 모르겠지만 문제가 어디에서 발생할 수 있는지 이해해야합니다. 분음 부호가있는 문자열에 대해 동일한 해시 코드를 얻으려면 다음을 수행하십시오. 구현 생성 이 메서드는 내부적이며 직접 사용할 수 없기 때문에 적절한 CultureAwareComparer.GetHashCode의 객체의 IEqualityComparer<T>를 리플렉션을 통해 호출하는 GetHashCode를 구현하는 CompareInfo의. 그러나 올바른 GetHashCodeOfString로 직접 호출하면 원하는 결과가 생성됩니다. 다음 예를 참조하세요. 라코 디스

출력은 다음과 같습니다. 라코 디스

나는 그것이 해킹처럼 보이는 것을 알고 있지만, 디 컴파일 된 .NET 코드를 조사한 후에 일반 기능이 필요한 경우에 다른 옵션이 있는지 확실하지 않습니다. 따라서 완전히 정확하지 않은 API를 사용하여 함정에 빠지지 않도록하십시오.
업데이트 :
또한 "SQL과 유사한 비교 자"의 잠재적 구현에 대한 요점을 만들었습니다. CompareOptions 사용. 또한 충분한주의를 기울여야합니다. "string pitfalls"를 검색 할 수있는 위치 코드 기반에서 문자열 비교, 해시 코드, 동등성을 "SQL 데이터 정렬과 유사"로 변경해야하는 경우 해당 위치가 100 % 손상되므로 가능한 모든 위치를 찾아서 검사해야합니다. 부서진다.
업데이트 # 2 :
GetHashCode ()가 CompareOptions를 처리하도록하는 더 좋고 깨끗한 방법이 있습니다. 클래스
SortKey 는 CompareOptions와 올바르게 작동하며 를 사용하여 검색 할 수 있습니다. <인용구>

CompareInfo.GetSortKey (yourString, yourCompareOptions) .GetHashCode ()

다음은 .NET 소스 코드에 대한 링크 입니다. 및 구현.

SQL Server의 Server.GetStringComparer 가 유용 할 수 있습니다.

다음은 훨씬 간단합니다. 라코 디스

https ://docs.microsoft.com/en-us/dotnet/api/system.globalization.globalizationextensions?view=netframework-4.8

주어진 옵션이 주어지면 해시 코드를 올바르게 계산합니다. 후행 공백은 ANSI SQL에서 삭제되지만 .net에서는 삭제되지 않으므로 수동으로 정리해야합니다.

다음은 공백을 정리하는 래퍼입니다. 라코 디스

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top