2015-09-25 82 views
0

我想「OPTION(RECOMPILE)」添加到我的一些NHibernate的查詢結束。我發現下面的帖子:NHibernate的LINQ添加查詢提示

http://www.codewrecks.com/blog/index.php/2011/07/23/use-sql-server-query-hints-with-nhibernate-hql-and-icriteria/

這說明我如何添加一個攔截器來追加SQL。但是他們使用ICriteria,而我使用LINQ來查詢我的數據。理想情況下,我想可以這樣說:

var query = session.Query<Foo>().OptionRecompile().ToList(); 

我想知道是否有可能增加一個擴展方法的IQueryable將注入一些字符串到查詢,我就可以在我的攔截器檢測的。這與上面的文章中使用的方法類似,他們添加了評論並檢測了這一點。

有關的進一步信息。我之前已經處理過LINQ擴展,並且我知道您可以使用HQL生成器添加擴展屬性/方法。但是從我的理解,這將只允許我說:

var query = session.Query<Foo>().Where(f => f.Bar.OptionRecompile()).ToList(); 

這不是理想的,似乎更多的是黑客攻擊。如果有人能幫忙,我會很感激。由於

回答

1

我就遇到了這個問題,最近也。我們想出了一個相當不錯的解決方案。重要的是它利用Rhino.Commons.LocalData提供執行範圍。

// First part 
using System; 
using System.Collections; 
using System.Web; 
using Rhino.Commons.LocalDataImpl; 

namespace Rhino.Commons 
{ 
    /// <summary> 
    /// This class is key for handling local data, data that is private 
    /// to the current context, be it the current thread, the current web 
    /// request, etc. 
    /// </summary> 
    public static class Local 
    { 
     static readonly ILocalData current = new LocalData(); 
     static readonly object LocalDataHashtableKey = new object(); 
     private class LocalData : ILocalData 
     { 
      [ThreadStatic] 
      static Hashtable thread_hashtable; 

      private static Hashtable Local_Hashtable 
      { 
       get 
       { 
        if (!RunningInWeb) 
        { 
         return thread_hashtable ?? 
         (
          thread_hashtable = new Hashtable() 
         ); 
        } 
        Hashtable web_hashtable = HttpContext.Current.Items[LocalDataHashtableKey] as Hashtable; 
        if(web_hashtable==null) 
        { 
         HttpContext.Current.Items[LocalDataHashtableKey] = web_hashtable = new Hashtable(); 
        } 
        return web_hashtable; 
       } 
      } 

      public object this[object key] 
      { 
       get { return Local_Hashtable[key]; } 
       set { Local_Hashtable[key] = value; } 
      } 

      public void Clear() 
      { 
       Local_Hashtable.Clear(); 
      } 
     } 

     /// <summary> 
     ///  Gets the current data 
     /// </summary> 
     /// <value>The data.</value> 
     public static ILocalData Data 
     { 
      get { return current; } 
     } 

     /// <summary> 
     ///  Gets a value indicating whether running in the web context 
     /// </summary> 
     /// <value><c>true</c> if [running in web]; otherwise, <c>false</c>.</value> 
     public static bool RunningInWeb 
     { 
      get { return HttpContext.Current != null; } 
     } 
    } 
} 

// Second part 
using System; 
using Rhino.Commons; 

namespace IDL.Core.Util.NHibernate 
{ 
    public class NhSqlAppender : IDisposable 
    { 
     private static string sql; 
     private int usages = 1; 

     public NhSqlAppender() 
     { 
     } 

     public NhSqlAppender(string sqlToAppend) 
     { 
      sql = sqlToAppend; 
     } 

     public static NhSqlAppender Append(string sqlToAppend) 
     { 
      var currentAppender = Current; 

      if (currentAppender == null) 
      { 
       Current = new NhSqlAppender(sqlToAppend); 
       currentAppender = Current; 
      } 
      else 
       currentAppender.IncrementUsages(); 

      return currentAppender; 
     } 

     public static NhSqlAppender Current 
     { 
      get { return Local.Data["NhSqlAppender"] as NhSqlAppender; } 
      protected set { Local.Data["NhSqlAppender"] = value; } 
     } 

     public static string Sql 
     { 
      get { return (IsValid) ? sql : string.Empty; } 
     } 

     public static bool AppendSql 
     { 
      get { return IsValid; } 
     } 

     public void IncrementUsages() 
     { 
      ++usages; 
     } 

     public void DecrementUsages() 
     { 
      --usages; 
     } 

     private static bool IsValid 
     { 
      get { return (Current != null && !string.IsNullOrWhiteSpace(sql)); } 
     } 

     public void Dispose() 
     { 
      if (usages <= 1) 
       Current = null; 
      else 
       DecrementUsages(); 
     } 
    } 
} 

// Third part 
namespace IDL.Core.Util.NHibernate 
{ 
    public class NhQueryHint : NhSqlAppender 
    { 
     public static NhSqlAppender Recompile() 
     { 
      return Append("OPTION(RECOMPILE)"); 
     } 
    } 
} 

// Fourth part 
using System; 
using IDL.Core.Util.NHibernate; 
using NHibernate; 

namespace IDL.Core.Configuration 
{ 
    [Serializable] 
    public class NhSqlAppenderInterceptor : EmptyInterceptor 
    { 
     public override NHibernate.SqlCommand.SqlString OnPrepareStatement(NHibernate.SqlCommand.SqlString sql) 
     { 
      if (NhSqlAppender.AppendSql) 
       return sql.Insert(sql.Length, (" " + NhSqlAppender.Sql)); 

      return base.OnPrepareStatement(sql); 
     } 
    } 
} 

// Fifth part 
// You need to register the interceptor with NHibernate 
// cfg = NHibernate.Cfg.Configuration 
cfg.SetInterceptor(new NhSqlAppenderInterceptor()); 

// Finally, usage 
using (NhQueryHint.Recompile()) 
    var results = IQueryable<T>.ToList(); 

您必須修改以適合您的環境。希望能幫助到你!

+0

剛剛有了一個機會來測試這一點,它的工作原理治療。謝謝你的幫助。 – nfplee

+0

太棒了!樂於幫助。這一個花了幾天時間縮小。 :) – jvukovich