我需要知道一種方法來在我的系統中實現一個驅動程序或方言,只要我在Nhibernate中執行SELECT,SELECT就會添加with(nolock ) 用它。 我需要在C#和NHibernate中,而不是直接在數據庫中!方言/驅動程序 - 每執行一個SELECT,添加(nolock)
希望你能理解!
謝謝!
我需要知道一種方法來在我的系統中實現一個驅動程序或方言,只要我在Nhibernate中執行SELECT,SELECT就會添加with(nolock ) 用它。 我需要在C#和NHibernate中,而不是直接在數據庫中!方言/驅動程序 - 每執行一個SELECT,添加(nolock)
希望你能理解!
謝謝!
有可能使用攔截並重寫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());
使用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?。
希望這可以幫助別人, 我使用此代碼添加鎖定提示大多數查詢,與答案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;
}
}
有此代碼的兩個錯誤:
這裏是修復:
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;
}
}
我的問題是,我需要看與(NOLOCK)在我的查詢中。我的意思是,任何選擇在我的數據庫中執行必須有(nolock)。 EX。 '從客戶'選擇*。執行此操作時,必須將其設置爲使用(nolock)'從客戶端'選擇*。謝謝 ! – Leonardo 2012-03-29 20:53:57
好的。正如我所說,READ UNCOMMITED隔離級別與WITH(NOLOCK)提示具有相同的效果。請解釋爲什麼這個解決方案不適合你。 – dillenmeister 2012-03-29 21:02:46
我的意思是。我知道它可行,但我的客戶希望在所有選擇結束時看到nolock。所以這就是爲什麼我需要使用方言或驅動程序來做到這一點! – Leonardo 2012-03-29 21:11:37