方言/驱动程序 - 我执行的每个SELECT,添加(nolock)

时间:2012-03-29 20:27:50

标签: c# nhibernate

我需要知道一种在我的系统中实现的方法,一个Driver或Dialect,每当我在Nhibernate中执行SELECT时,SELECT都会添加with(nolock)。 我需要它在C#和NHibernate中,而不是直接在DB中!

希望你能理解!

谢谢!

4 个答案:

答案 0 :(得分: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?

答案 1 :(得分:2)

可以使用Interceptor修改sql并覆盖OnPrepareStatement方法,如下所示:

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 :(得分: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;
        }
    }

答案 3 :(得分:0)

此代码中有两个错误:

  1. 对于具有参数的SQL脚本此代码不起作用。
  2. SqlString.Parts不是编译,我使用的是NHibernate 4.0.0.4000
  3. 以下是修复:

    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;
            }
    }