2012-03-29 47 views

回答

2

有可能使用攔截並重寫OnPrepareStatement方法,像這樣修改SQL:

public class AddNoLockHintsInterceptor : EmptyInterceptor 
{ 
    public override SqlString OnPrepareStatement(SqlString sql) 
    { 
     // Modify the sql to add hints 

     return sql; 
    } 
} 

,這裏是一個方法來註冊與NHibernate攔截器:

var session = SessionFactory.OpenSession(new AddNoLockHintsInterceptor()); 
2

使用WITH(NOLOCK)提示與使用READ UNCOMMITED事務隔離級別相同:When should you use "with (nolock)"

與NHibernate開始新的交易時,您可以指定事務隔離級別:

var session = SessionFactory.OpenSession(); 
session.BeginTransaction(IsolationLevel.ReadUncommitted); 

我不會推薦這個除非你真的知道你雖然做什麼。以下是關於此主題的更多信息:Why use a READ UNCOMMITTED isolation level?

+0

我的問題是,我需要看與(NOLOCK)在我的查詢中。我的意思是,任何選擇在我的數據庫中執行必須有(nolock)。 EX。 '從客戶'選擇*。執行此操作時,必須將其設置爲使用(nolock)'從客戶端'選擇*。謝謝 ! – Leonardo 2012-03-29 20:53:57

+0

好的。正如我所說,READ UNCOMMITED隔離級別與WITH(NOLOCK)提示具有相同的效果。請解釋爲什麼這個解決方案不適合你。 – dillenmeister 2012-03-29 21:02:46

+0

我的意思是。我知道它可行,但我的客戶希望在所有選擇結束時看到nolock。所以這就是爲什麼我需要使用方言或驅動程序來做到這一點! – Leonardo 2012-03-29 21:11:37

1

希望這可以幫助別人, 我使用此代碼添加鎖定提示大多數查詢,與答案dillenmeister

public class NoLockHintsInterceptor : EmptyInterceptor 
    { 
     public override SqlString OnPrepareStatement(SqlString sql) 
     { 
      // Modify the sql to add hints 
      if (sql.StartsWithCaseInsensitive("select")) 
      { 
       var parts = new List<object>((object[]) sql.Parts); 
       object fromItem = parts.FirstOrDefault(p => p.ToString().ToLower().Trim().Equals("from")); 
       int fromIndex = fromItem != null ? parts.IndexOf(fromItem) : -1; 
       object whereItem = parts.FirstOrDefault(p => p.ToString().ToLower().Trim().Equals("where")); 
       int whereIndex = whereItem != null ? parts.IndexOf(whereItem) : parts.Count; 

       if (fromIndex == -1) 
        return sql; 

       parts.Insert(parts.IndexOf(fromItem) + 2, " with(nolock) "); 
       for (int i = fromIndex; i < whereIndex; i++) 
       { 
        if (parts[i - 1].Equals(",")) 
        { 
         parts.Insert(i + 2, " with(nolock) "); 
         i += 2; 
        } 
        if (parts[i].ToString().Trim().EndsWith(" on")) 
        { 
         parts[i] = parts[i].ToString().Replace(" on", " with(nolock) on "); 
        } 
       } 
       sql = new SqlString(parts.ToArray()); 
      } 
      return sql; 
     } 
    } 
0

有此代碼的兩個錯誤:

  1. 對於具有參數此代碼將無法正常工作SQL腳本。
  2. SqlString.Parts不編譯,我使用NHibernate 4.0.0.4000

這裏是修復:


public class NoLockInterceptor : EmptyInterceptor 
{ 
    public override SqlString OnPrepareStatement(SqlString sql) 
     { 
      //var log = new StringBuilder(); 
      //log.Append(sql.ToString()); 
      //log.AppendLine(); 

      // Modify the sql to add hints 
      if (sql.StartsWithCaseInsensitive("select")) 
      { 
       var parts = sql.ToString().Split().ToList(); 
       var fromItem = parts.FirstOrDefault(p => p.Trim().Equals("from", StringComparison.OrdinalIgnoreCase)); 
       int fromIndex = fromItem != null ? parts.IndexOf(fromItem) : -1; 
       var whereItem = parts.FirstOrDefault(p => p.Trim().Equals("where", StringComparison.OrdinalIgnoreCase)); 
       int whereIndex = whereItem != null ? parts.IndexOf(whereItem) : parts.Count; 

       if (fromIndex == -1) 
        return sql; 

       parts.Insert(parts.IndexOf(fromItem) + 3, "WITH (NOLOCK)"); 
       for (int i = fromIndex; i < whereIndex; i++) 
       { 
        if (parts[i - 1].Equals(",")) 
        { 
         parts.Insert(i + 3, "WITH (NOLOCK)"); 
         i += 3; 
        } 
        if (parts[i].Trim().Equals("on", StringComparison.OrdinalIgnoreCase)) 
        { 
         parts[i] = "WITH (NOLOCK) on"; 
        } 
       } 
       // MUST use SqlString.Parse() method instead of new SqlString() 
       sql = SqlString.Parse(string.Join(" ", parts)); 
      } 

      //log.Append(sql); 
      return sql; 
     } 
}