将SQL查询选项添加到NHibernate查询

时间:2010-08-27 13:44:31

标签: .net sql-server nhibernate castle-activerecord

我正在使用一些为NHibernate生成ICriteria查询的代码。它们使用ActiveRecord和ActiveRecordMediator.FindAll()

执行

对于某些查询,我需要通过在SELECT语句末尾添加OPTION (HASH JOIN)提示来优化它们。有没有快速的方法可以做到这一点?

我不想使用纯SQL重写查询。嗯,我很乐意,但他们太复杂了。但是,例如,如果有一种简单的方法可以在将SQL抽取到SQL Server之前对其进行陷阱和修改,我会很高兴。

2 个答案:

答案 0 :(得分:4)

实现IInterceptor并在OnPrepareStatement()中进行修改。然后将您的拦截器传递给ISessionFactory.OpenSession()。

Here's an example

或者您可以尝试在方言中注册自定义功能。 (example

答案 1 :(得分:3)

尽管Mauricio Scheffer的回答非常有用,但我还是希望用实际的Interceptor扩展它以实现与NHibernate和Castle Active Records一起使用的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_");
    }
}
}

使用设施连接拦截器

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

上面的类创建了一个Active Record for Facility。我们将它连接到Global.asax.cs文件中,如下所示:

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

在Application.cs文件中,我们添加了这样的工具:

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

结论 的 容器现在包含连接全文搜索拦截器的工具,该拦截器将拦截所有ActiveRecordMediator调用。

我们在现有系统中没有更改过一行代码,但我们已经添加了以简单而有效的方式分析所有SQL Request操作的功能。

特别感谢Donn Felker