NHibernate 2nd lvl cache, custom query, sqldialect

泄露秘密 提交于 2019-11-29 14:52:17

I had a similar issue (removing SetMaxResults also helped but I needed paging) and found out that the following NHibernate configuration property was causing this bug:

<property name="use_sql_comments">true</property>

It's certainly a bug, because the GetAfterSelectInsertPoint method doesn't take into account that SQL comments may be prepended to the SQL query.

Just set the use_sql_comments property to false and the problem disappears.

I repaired the bug using Alkampfer's solution, but I created my own SQL dialect rather than patching the NHibernate source directly:

public class Sql2008DialectWithBugFixes : MsSql2008Dialect
{
    public override SqlString GetLimitString(SqlString querySqlString, int offset, int last)
    {
        if (offset == 0)
        {
            return querySqlString.Insert(GetAfterSelectInsertPoint(querySqlString), " top " + last);
        }

        return base.GetLimitString(querySqlString, offset, last);
    }

    private static int GetAfterSelectInsertPoint(SqlString sql)
    {
        Int32 selectPosition;

        if ((selectPosition = sql.IndexOfCaseInsensitive("select distinct")) >= 0)
        {
            return selectPosition + 15; // "select distinct".Length;

        }
        if ((selectPosition = sql.IndexOfCaseInsensitive("select")) >= 0)
        {
            return selectPosition + 6; // "select".Length;
        }

        throw new NotSupportedException("The query should start with 'SELECT' or 'SELECT DISTINCT'");
    }
}

Just had the same problem using a similar query which has a WITH clause.

Unfortunately, my query populates a grid, with paging, so I have to keep SetMaxResults.

My solution was to rewrite using a Derived Table:

var sql = @"with Foo(col1,col2,col3)
              as (select x1, x2, x3 from x join y blabla)
            Select col1, col2, col3 from Foo
            join B on B.col1 = Foo.col1";

becomes

var sql = @"Select col1, col2, col3 from 
           (select x1 as col1, x2 as col2, x3 as col3 
            from x join y blabla) as Foo
           join B on B.col1 = Foo.col1";

Just to allow NHibernate to insert the " TOP x " string after the "select" string (6 characters from the begining)... No comment :(

T

It seems that there is some strange bug in the routine used to find the place in the query to insert the TOP clause (GetAfterSelectInsertPoint ) as told by Sandor. You can fix it directly in nh source (I actually patched 2.1 version I'm using in a project, you can find details here). So if you absolutely needs to enable comments with use_sql_comments you can :)

I encountered this problem when upgrading from 1.2 to 3.2 (I know, BIG jump eh?).

The issue in my case was that there is a leading space in front of the select statement in the hql, e.g. String hql = " select "...

With SQL2005 Dialect, this crashes with a "System.NotSupportedException: The query should start with 'SELECT'..." message.

The solution is to

  1. create a unit test that fails, a good Test Driven Developer should :)
  2. remove the leading space from the " select..." statement
  3. build and run the unit test

Just as i predicted - unbounding select is acceptable workaround.

Deleted SetMaxResults and it works.

We ran into this issue when upgrading to NHibernate version 3.3, but for a different reason...whitespace. We had a lot of sql strings that looked like this:

var sql = @"
select col1 from MyTable";

or:

var sql = @" select col1 from My Table";

These resulted in the "The query should start with 'SELECT' or 'SELECT DISTINCT'" errors because NHibernate doesn't trim the string before validating it.

We created a new dialect that trims the string first to get around this:

public class Sql2008DialectCustom : MsSql2008Dialect
{
  public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit)
  {
    var trimmedQueryString = queryString.Trim();
    return base.GetLimitString(trimmedQueryString, offset, limit);
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!