Dialect/Driver - Every SELECT I perform, add with(nolock)

后端 未结 4 598
猫巷女王i
猫巷女王i 2020-12-18 17:00

I need to know a way to implement in my system, a Driver or Dialect which, whenever I perform a SELECT in Nhibernate, the SELECT adds the with(nolock) with it. I need that t

相关标签:
4条回答
  • 2020-12-18 17:16

    Using the WITH(NOLOCK) hint is the same thing as using a READ UNCOMMITED transaction isolation level as discussed here: When should you use "with (nolock)".

    You can specify the transaction isolation level when starting new transactions with NHibernate:

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

    I would not recommend this unless you really know what you are doing though. Here's some more information on the subject: Why use a READ UNCOMMITTED isolation level?.

    0 讨论(0)
  • 2020-12-18 17:24

    Hope this would help someone, I used this code to add no lock hints to the most of the queries, related to the answer 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 讨论(0)
  • 2020-12-18 17:30

    There are two errors in this code:

    1. For SQL script that has parameter This code won't work.
    2. SqlString.Parts is not compile, I am using NHibernate 4.0.0.4000

    Here is the Fix:


    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;
            }
    }
    
    0 讨论(0)
  • 2020-12-18 17:40

    It is possible to modify the sql using an Interceptor and overriding the OnPrepareStatement method, something like this:

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

    And here is a way to register the interceptor with NHibernate:

    var session = SessionFactory.OpenSession(new AddNoLockHintsInterceptor());
    
    0 讨论(0)
提交回复
热议问题