1

NHibernate를 사용하여 매핑 된 개체를 "가져 오는"경우 SELECT 쿼리가 데이터베이스에 출력됩니다. 그것은 매개 변수를 사용하여 이것을 출력합니다. 나는 세입자의 ID와 이름을 기반으로 자동차의 목록을 조회 할 경우 그래서, 내가 얻을 :매개 변수에 관한 NHIbernate 검색 쿼리 출력 제어

select Name, Location from Car where [email protected] and [email protected]

이 우리의 생성 데이터베이스 (캐싱)이 쿼리 및 결과에 따라 쿼리 계획의 좋은 이점이있다 , 다시 실행될 때 쿼리는 캐시에서 계획을로드 할 수 있기 때문에 훨씬 빠릅니다.

이 문제는 우리가 멀티 테넌트 데이터베이스이며 거의 모든 우리 인덱스가 파티션에 맞춰져 있다는 것입니다. 우리의 거주자들은 매우 다른 데이터 세트를 가지고 있습니다. 1 명의 거주자는 5 대의 자동차를 소유 할 수 있고, 다른 하나는 5 만 대의 자동차를 가질 수 있습니다. 그래서 NHibernate는 이것을 수행하기 때문에, 데이터베이스를 실행하는 FIRST 세입자를위한 계획을 생성하고 캐싱하는 순수한 효과가 있습니다. 이 계획은 쿼리를 실행하는 차후 세입자에게는 효율적이지 않을 수 있습니다.

나는 NHibernate가 특정 매개 변수를 매개 변수화하지 않도록 강제하고있다. 즉, 임차인 ID. 그래서 쿼리가 읽고 싶은 것 :

select Name, Location from Car where tenantID=55 and [email protected]

나는 HBM.XML 매핑에이 작업을 수행하는 방법을 알아낼 수 없습니다. 어떻게 NHibernate에 매개 변수 사용법을 지시 할 수 있습니까? 아니면 매개 변수를 모두 해제 할 수 있습니까?

+0

이것은 매개 변수 스니핑 문제로 보입니다. 이는 보통 일부 색인이 누락되거나 부적합 함을 의미합니다. IMO, 매개 변수화하지 않음으로써 문제를 해결하는 것이 아니라이를 더 잘 수정하십시오. 특히 SQL Server가 리터럴을 자동으로 매개 변수화 할 수 있기 때문에 특히 그렇습니다. 이 모든 것에 대한 자세한 내용은이 [blog] (http://www.sommarskog.se/query-plan-mysteries.html)을 참조하십시오. –

답변

0

OK 모두들, 알아 냈습니다.

나는 그것이 다음과 같습니다 내 자신의 사용자 정의 드라이버와 SqlClientDriver을 무시하고 한 방법 :

public class CustomSqlClientDriver : SqlClientDriver 
{ 
    private static Regex _partitionKeyReplacer = new Regex(@".PartitionKey=(@p0)", RegexOptions.Compiled); 
    public override void AdjustCommand(IDbCommand command) 
    { 
     var m = _tenantIDReplacer.Match(command.CommandText); 

     if (!m.Success) 
      return; 

     // replace the first parameter with the actual partition key 
     var parameterName = m.Groups[1].Value; 

     // find the parameter value 
     var tenantID = (IDbDataParameter) command.Parameters[parameterName]; 
     var valueOfTenantID = tenantID.Value; 

     // now replace the string 
     command.CommandText = _tenantIDReplacer.Replace(command.CommandText, ".TenantID=" + valueOfTenantID); 
    } 
} } 

내가 AdjustCommand 방법을 무시하고 tenantID을 대체 할 정규식을 사용합니다. 이 작품; 만약 더 좋은 방법이 있는지 확실하지 않지만 나는 정말로은 NHibernate를 열어서 코어 코드를 망쳐 놓기를 원하지 않았다.

당신은 초기화시 SessionFactory를connection.driver_class 속성이 사용자 정의 드라이버를 등록해야합니다.

희망이 있으면 도움이됩니다.

+0

문제가 해결되고 다른 답변을 사용할 수없는 경우 사용자가 원하는대로 대답을 수락 할 수 있습니다. 답을 수락 한 질문을 더 많이 봅니다. –

+1

이것을하기 위해서 ['IInterceptor'] (http://nhibernate.info/doc/nhibernate-reference/events.html)를 사용할 수 있습니다. ('EmptyInterceptor'에서 파생되고, 당신이하는 것과 같은 방식으로 sql을 변경하기위한'OnPrepareStatement' 함수를 오버라이드하고, 그것을 열 때 세션에 삽입하거나 전역 설정에서 정의하십시오.) –