2010-08-27 7 views
0

Je travaille avec du code qui génère des requêtes ICriteria pour NHibernate. Ils sont exécutés en utilisant ActiveRecord et ActiveRecordMediator.FindAll()Ajout d'options de requête SQL à la requête NHibernate

Pour certaines requêtes, j'ai besoin de les optimiser en ajoutant un indice OPTION (HASH JOIN) à la fin de l'instruction SELECT. Y a-t-il un moyen rapide de le faire?

Je ne souhaite pas réécrire les requêtes à l'aide de SQL simplifié. J'adorerais, mais ils sont trop compliqués. Mais si, par exemple, il est facile de piéger et de modifier le code SQL avant de le transférer vers SQL Server, je serais heureux.

Répondre

4

Implémentez un IInterceptor et effectuez vos modifications dans OnPrepareStatement(). Passez ensuite votre intercepteur à ISessionFactory.OpenSession().

Here's an example.

Ou vous pouvez essayer d'enregistrer une fonction personnalisée dans votre dialecte. (example)

+0

J'ai eu enfin la chance d'essayer. Cela fonctionne, même si c'était assez pénible d'y arriver. Merci –

3

Alors que la réponse de Mauricio Scheffer est extrêmement utile, j'ai décidé de l'étendre avec un exemple de travail pour implémenter Interceptor à utiliser avec NHibernate et Castle Active Records.

L'Interceptor

using NHibernate; 
using NHibernate.SqlCommand; 

namespace Common.FTS 
{ 

public class FtsHashInterceptor : EmptyInterceptor 
{ 
    private static FtsHashInterceptor instance = new FtsHashInterceptor(); 

    protected FtsHashInterceptor() { } 

    public static FtsHashInterceptor Instance 
    { 
     get { return instance; } 
     set { instance = value; } 
    } 

    public override SqlString OnPrepareStatement(SqlString sql) 
    { 
     return sql.Replace("inner join Product fts1_", "inner hash join Product fts1_"); 
    } 
} 
} 

Câblage du Interceptor avec une facilité

using Castle.ActiveRecord.Framework; 
using Castle.Core.Configuration; 
using Castle.MicroKernel; 
using NHibernate; 

namespace Common.FTS 
{ 
/// 
/// Allows for the system to pick up the audit facility which will be used to 
/// audit all transactions in the system. 
/// 
public class FtsHashFacility : IFacility 
{ 
    #region IFacility Members 

    public void Init(IKernel kernel, IConfiguration facilityConfig) 
    { 
     InterceptorFactory.Create = new InterceptorFactory.CreateInterceptor(CreateFtsHashInterceptor); 
    } 

    public void Terminate() 
    { 
     // Nothing to terminate 
    } 

    #endregion 

    private IInterceptor CreateFtsHashInterceptor() 
    { 
     return FtsHashInterceptor.Instance; 
    } 
} 
} 

La classe crée une Facilité ci-dessus Active Record. Nous câbler ce dans le fichier Global.asax.cs comme ceci:

static private IWindsorContainer _container; 

protected void Application_Start(object sender, EventArgs e) 
{ 
try 
{ 
    _container = new WindsorContainer(Server.MapPath("~/config/windsor.config")); 
    var app = _container.Resolve(); 
    app.RegisterFacilities(_container); 
    app.RegisterComponents(_container); 
} 
} 

Dans le fichier Application.cs nous ajoutons l'installation en tant que tel:

public void RegisterFacilities(IWindsorContainer container) 
{ 
container.AddFacility("fts.support", new FtsHashFacility()); 
} 

Conclusion Le conteneur contient maintenant la fonction qui va connecter l'intercepteur Full Text Search qui interceptera tous les appels ActiveRecordMediator.

Nous n'avons pas modifié une ligne de code dans notre système existant, mais nous avons ajouté la possibilité d'analyser toutes nos opérations SQL Request d'une manière simple mais efficace.

Merci spécial à Donn Felker