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

发布于 2024-09-16 03:29:41 字数 295 浏览 6 评论 0原文

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

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

我不想使用普通 SQL 重写查询。嗯,我很愿意,但是它们太复杂了。但是,例如,如果有一种简单的方法可以在将 SQL 发送到 SQL Server 之前捕获并修改 SQL,我会很高兴。

I'm working with some code that generates ICriteria queries for NHibernate. They get executed using ActiveRecord and ActiveRecordMediator.FindAll()

For certain queries, I need to optimise them by adding on an OPTION (HASH JOIN) hint at the end of the SELECT statement. Is there a quick way I can do this?

I don't want to rewrite the queries using plain SQL. Well, I'd love to, but they're too complicated. But if, for example, there's an easy way I can trap and modify the SQL before it's pumped off to SQL Server, I'd be happy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

递刀给你 2024-09-23 03:29:41

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

这是一个示例

或者您可以尝试用您的方言注册自定义函数。 (示例

Implement an IInterceptor and do your modifications in OnPrepareStatement(). Then pass your interceptor to ISessionFactory.OpenSession().

Here's an example.

Or you could try registering a custom function in your dialect. (example)

我很OK 2024-09-23 03:29:41

虽然 Mauricio Scheffer 的回答非常有用,但我决定用工作示例来扩展它,以实现与 NHibernate 和 Castle Active Records 一起使用的拦截器。

拦截器

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 创建了一个设施。我们将其连接到 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 请求操作的功能。

特别感谢 Donn Felker

While answer of Mauricio Scheffer is extremly useful I've desided to extend it with working sample for implementing Interceptor to be used with NHibernate and Castle Active Records.

The 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_");
    }
}
}

Wiring up the Interceptor with a Facility

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

The class above creates a Facility for Active Record. We wire this up in the Global.asax.cs file like so:

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

In the Application.cs file we add the facility as such:

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

Conclusion
The container now contains the facility which will wire up the Full Text Search interceptor which will intercept all ActiveRecordMediator calls.

We have not changed a line of code in our existing system, yet we have added the ability to analyse all of our SQL Request operations in a simple yet effective manner.

Special Thanks to Donn Felker

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文