2015-09-25 52 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