2010-08-27 91 views
0

我正在處理一些生成NHibernate的ICriteria查詢的代碼。他們得到執行使用ActiveRecord和ActiveRecordMediator.FindAll()將SQL查詢選項添加到NHibernate查詢

對於某些查詢,我需要通過在SELECT語句的末尾添加OPTION (HASH JOIN)提示來優化它們。有沒有快速的方法,我可以做到這一點?

我不想用普通的SQL重寫查詢。那麼,我很樂意,但他們太複雜了。但是,舉例來說,如果有一種簡單的方法,我可以在將SQL傳遞到SQL Server之前對其進行陷阱和修改,我很高興。

回答

4

實現IInterceptor並在OnPrepareStatement()中進行修改。然後將你的攔截器傳遞給ISessionFactory.OpenSession()。

Here's an example

或者你可以嘗試在你的方言中註冊一個自定義函數。 (example

+0

我終於有機會嘗試這個。它的工作原理,雖然到達那裏非常痛苦。謝謝 – 2010-09-03 20:21:37

3

雖然Mauricio Scheffer的回答非常有用,但我希望將它擴展爲實現用於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; 
    } 
} 
} 

類以上創建活動記錄的工具。我們在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