我正在使用一些为NHibernate生成ICriteria查询的代码。它们使用ActiveRecord和ActiveRecordMediator.FindAll()
执行对于某些查询,我需要通过在SELECT语句末尾添加OPTION (HASH JOIN)
提示来优化它们。有没有快速的方法可以做到这一点?
我不想使用纯SQL重写查询。嗯,我很乐意,但他们太复杂了。但是,例如,如果有一种简单的方法可以在将SQL抽取到SQL Server之前对其进行陷阱和修改,我会很高兴。
答案 0 :(得分:4)
实现IInterceptor并在OnPrepareStatement()中进行修改。然后将您的拦截器传递给ISessionFactory.OpenSession()。
或者您可以尝试在方言中注册自定义功能。 (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