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

Смежные вопросы