2010-03-22 5 views
4

우리가 사용하고있는 코드는 검색 쿼리의이 부분에 솔직하다 :NHibernate 기준을 사용하여 LIKE 절을 이스케이프하려면 어떻게해야합니까?

myCriteria.Add(
    Expression.InsensitiveLike("Code", itemCode, MatchMode.Anywhere));

이 프로덕션 환경에서 잘 작동합니다.

고객 중 한 명이이 쿼리와 일치해야하는 % 기호가 포함 된 항목 코드가 있습니다. 이 코드의 결과 SQL 출력은 다음과 유사합니다.

SELECT ... FROM ItemCodes WHERE ... AND Code LIKE '%ItemWith%Symbol%'

이는 항목 검색에서 왜 이상한 결과가 발생하는지 분명하게 설명합니다.

프로그래밍 방식 Criteria 방법을 사용하여 이스케이프를 사용하도록 설정하는 방법이 있습니까?


부록 : 우리는 2.1.0.4000 (글을 쓰는 현재는 2.1.2.4853입니다) NHibernate에의 약간 이전 버전을 사용하고,하지만 난 릴리스 노트를 확인하고 있었다

없음 이것에 대한 수정에 대한 언급. 나는 그들의 bugtracker 중 어떤 미해결 문제도 발견하지 못했습니다.

우리는 특수 문자 (%, _, [, and ^)를 매우 쉽게 이스케이프 처리 할 수 ​​있도록 SQL Server를 사용하지만 NHibernate를 사용하는 요점은 응용 프로그램을 데이터베이스 엔진과 무관하게 만드는 것입니다 가능한 한 많이.

HqlQueryUtil.GetLikeExpr()도 입력을 이스케이프 처리하지 않으며 MatchMode 매개 변수를 제거하면 이스케이프 처리가 적용됩니다.


업데이트 : 나는 someone else이 같은 일을 (3 년 전) 할 역부족, 해상도 (이에 "고정"하고 내가 위에서 언급 한 방법에 escapeChar 과부하를 추가했다 버전 2.0.0.3347). 나는 그 문제에 대한 의견을 추가로 해결할 것을 요구했다.

답변

4

데이터베이스 독립성을 달성하기 위해 찾을 수있는 유일한 방법은 검색 문자열의 모든 문자를 이스케이프 처리하고 이전의 대답과 마찬가지로 LikeExpression에서 적절한 생성자를 호출하는 것입니다. 당신은 수동으로 수행하거나 LikeExpression을 확장 할 수 :

이스케이프 문자열 ( this question에 대한 답변과 의견을 참조)를 작성하는보다 효율적인 방법은 의심의 여지가
public class LikeExpressionEscaped : LikeExpression 
    { 
     private static string EscapeValue(string value) 
     { 
      var chars = value.ToCharArray(); 
      var strs = chars.Select(x => x.ToString()).ToArray(); 
      return "\\" + string.Join("\\", strs); 
     } 

     public LikeExpressionEscaped(string propertyName, string value, MatchMode matchMode, bool ignoreCase) 
      : base(propertyName, EscapeValue(value), matchMode, '\\', ignoreCase) 
     {} 
    } 

. 사용법 :

var exp = new LikeExpressionEscaped("Code", itemCode, MatchMode.Anywhere, true); 
myCriteria.Add(exp); 
+0

제이미, 도와 줘서 고마워. 내가 찾고있는 것이 존재하지 않는 것 같습니다 (질문 본문에 대한 내 업데이트 참조). 당신이 여기서 한 접근법은 내가 취할 방법입니다. 나는이 대답을 현재 받아 들일 것이며, NHibernate의 저자가 어떤 일을하기로 결정했다면, 나는 그 때이 문제를 다시 검토 할 것이다. –

+2

향후 방문자 : .NET 4를 사용하면 간단히'return @ "\"+ string.Join (@ "\", value.ToCharArray())'를 사용할 수 있습니다. 더 깨끗하고 나은 성능. – Bergius

+0

빈 문자열을 "\\"로 변환하지 않습니까? – Tobias

2

LikeExpression 인스턴스를 생성하여이를 수행 할 수 있습니다. 이 예에서 나는 (그 자체가 탈출해야합니다) 백 슬래시 %를 탈출하고있다 :이 오버로드를 사용하여 LikeExpression를 반환하는 정적 메서드를 보지 못했다

var itemCode = "ItemWith%Symbol"; 
itemCode = searchCode.Replace("%", "\\%"); 
var exp = new LikeExpression("Code", itemCode, MatchMode.Anywhere, '\\', true); 
myCriteria.Add(exp); 

.

그런데 SQL Server를 사용하는 경우 기본적으로 대/소문자를 구분하지 않습니다.

+0

답장을 보내 주셔서 감사합니다. 우리는 SQL Server를 사용하고 있지만 앞에서 말했듯이 NHibernate를 사용하는 것은 백엔드 데이터베이스를 인식하지 못하게 만드는 것입니다.내가 선택한 NHibernate 방언을 기반으로 작동하는 솔루션을 선호합니다. SQL Server에서'['문자는 이스케이프 문자이기도합니다. 나는 다른 방언의 사람들을 피하는 것이 효과적이라고 생각합니다. 그러나 내가 의미하는 바를 아는 경우에 그것은 정말로 깨끗하지 않습니다. 그리고 우리가'Like '와'InsensitiveLike'에 대한 이러한 호출을 데이터 영역을 통해 뿌렸으므로, 우리 자신의 롤링 대신에 내부 함수/옵션을 사용하는 것이 좋을 것입니다. –

+0

Jon, 귀하의 의견을 이해하지 못합니다. 내 대답은 대소 문자를 구분하지 않습니다. 실제 최종 매개 변수는 ignoreCase :'public LikeExpression (string propertyName, string value, char? escapeChar, bool ignoreCase)'에 대해 제공됩니다. 나는 SQL Server에 아무런 영향을 미치지 않는다는 것을 지적했다. 이스케이프 문자를 허용하는 InsensitiveLikeExpression에는 오버로드 된 생성자가 없습니다. –

+0

그 점을 이해합니다. 내가 말하고자하는 것은 SQL Server에는 다른 이스케이프 문자 ('[')가 있지만 다른 엔진은 이스케이프 문자가 아닙니다. 나는 적어도 하나의 이스케이프 문자를 거기에 넣을 것으로 추측하지만 모든 기존 코드는 변경해야하지만 SQL Server 이외의 엔진에서는 필자가하지 않아도 이스케이프 처리하지 않을 것입니다. –

관련 문제