1

NHibernateを使用してマップされたオブジェクトを「フェッチ」すると、SELECTクエリがデータベースに出力されます。パラメータを使用してこれを出力します。私はテナントIDと名前に基づいて車のリストを照会する場合は、私が手:このクエリと結果に基づいてパラメータに関するNHIbernate検索クエリの出力の制御

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

これが私達のデータベース作成(およびキャッシュ)の素敵な利点を持っているクエリプランしたがって、再度実行すると、キャッシュからプランをロードできるため、クエリがはるかに高速になります。

この問題は、私たちがマルチテナントデータベースであり、私たちのインデックスのほとんどすべてがパーティションアライメントされているということです。当社のテナントは、データセットが大きく異なります。 1台のテナントは5台の車を所有でき、もう1台は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をオーバーライドしてなかった方法:私はAdjustCommandメソッドをオーバーライドしてtenantIDを置き換えるために正規表現を使用し

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); 
    } 
} } 

。これはうまくいく。より良い方法があるかどうかわからないが、私は本当にはNHibernateをオープンしてコアコードを乱すことを望んでいませんでした。

あなたは、初期化時にのSessionFactoryconnection.driver_classプロパティでこのカスタムドライバを登録する必要があります。

これが誰かを助けることを願っています!

+0

問題が解決され、それ以外の回答が得られない場合は、オプションで自分の回答を受け入れることができます。受け入れられた回答を含む質問がより多く表示されます。 –

+1

これを行うために['IInterceptor'](http://nhibernate.info/doc/nhibernate-reference/events.html)を使うこともできます。 ( 'EmptyInterceptor'から派生し、同じ方法でsqlを変更するための' OnPrepareStatement'関数をオーバーライドし、オープン時にセッションに挿入するか、グローバルコンフィグレーションで定義します)。 –

関連する問題