문제

NH와 FNH의 트렁크 버전을 얻었습니다. 두 번째 레벨 캐시를 추가하려고 할 때 Nhibernate의 일부 부분은 선택한 sqldialect를 잊어 버립니다.


초기 구성 :

var cfg = Fluently.Configure()
  .Database(MsSqlConfiguration.MsSql2008
    .ConnectionString(connectionString)
    .DefaultSchema("dbo")
    .UseReflectionOptimizer()    
  .Mappings(m => ................);

유죄 사용자 정의 쿼리 :

var sql = @"with Foo(col1,col2,col3)
              as (select bla bla bla...)
            Select bla bla bla from Foo";

list = Session.CreateSQLQuery(sql)
  .AddEntity("fizz", typeof(Fizz))
  .SomethingUnimportant();

구성을 변경할 때 :

var cfg = Fluently.Configure()
  .Database(MsSqlConfiguration.MsSql2008
    .ConnectionString(connectionString)
    .DefaultSchema("dbo")
     .UseReflectionOptimizer()
     .Cache(c=>c
       .UseQueryCache()
         .ProviderClass<HashtableCacheProvider>())
       .ShowSql())
     .Mappings(m => ................);

쿼리는 오류를 던집니다 (WITH 조항은 MSSQL2008에 추가되었습니다.

쿼리는 'select'또는 'select'로 시작해야합니다.

NotSupportedException : 쿼리는 'select'또는 'select'로 시작해야합니다.] nhibernate.dialect.mssql2000dialect.getAfterselectinsertpoint (sqlstring sql) +179 nhibernate.dialect.mssql2000dialect.msql2000dialect.mstring (sqlstring), int322222212222122212221222212. .dialect.mssql2005dialect.getlimitstring (sqlstring querysqlstring, int32 int32 int32 last) +127 nhibernate.loader.loader.preparequerycommand (QueryParameters QueryParameters, QueSeciorItors espector, issessionimplementor session). , 부울 returnProxies) +352 nhibernate.loader.loader.loader.doqueryAndinitializenonLazyCollection (issessionimplementor 세션, QueryParameters QueryParameters, Boolean returnProxies) +114 nhibernate.loader.loader.dolist (issessionimplementor session, queryameters) queryameters


Nhibernate를 정확히 혼란스럽게하는 아이디어와 그것을 고치는 방법은 무엇입니까?


유죄 Nhibernate 코드 (nhibernate/divelect/mssql200dialect.cs) :

private static int GetAfterSelectInsertPoint(SqlString sql)
{
  if (sql.StartsWithCaseInsensitive("select distinct"))
  {
    return 15;
  }
  else if (sql.StartsWithCaseInsensitive("select"))
  {
    return 6;
  }
  throw new NotSupportedException
    ("The query should start with 'SELECT' or 'SELECT DISTINCT'");
  }
}

그거 봐요 .SetMaxResults(123) 이것을 원인합니다. 다행히도 해당 쿼리를 해제 할 수 있습니다.

바라건대 이것은 이것을 고칠 것입니다.

도움이 되었습니까?

해결책

비슷한 문제가있었습니다 (제거 SetMaxResults 또한 도움이되었지만 페이징이 필요했습니다.)

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

그것은 확실히 버그이기 때문입니다 GetAfterSelectInsertPoint 메소드는 SQL 댓글이 SQL 쿼리로 선정 될 수 있다는 것을 고려하지 않습니다.

그냥 설정하십시오 use_sql_comments 속성 false 그리고 문제가 사라집니다.

다른 팁

Alkampfer의 솔루션을 사용하여 버그를 수리했지만 Nhibernate 소스를 직접 패치하는 대신 내 자신의 SQL 방언을 만들었습니다.

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'");
    }
}

with 절이있는 유사한 쿼리를 사용하여 동일한 문제가있었습니다.

불행히도, 내 쿼리는 페이징으로 그리드를 채 웁니다. 그래서 setMaxResults를 유지해야합니다.

내 해결책은 파생 된 테이블을 사용하여 다시 쓰는 것입니다.

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

NHibernate가 "select"문자열 (시작에서 6 자) 다음에 "상단 X"문자열을 삽입하도록하기 위해 ... 댓글 없음 :(

Sandor가 말한대로 상단 절 (getAfterselectinsertPoint)을 삽입하기 위해 쿼리에서 장소를 찾는 데 사용되는 일상에 이상한 버그가있는 것 같습니다. NH 소스에서 직접 수정할 수 있습니다 (실제로 프로젝트에서 사용중인 2.1 버전을 패치했습니다. 여기에서 세부 정보를 찾으십시오). 따라서 use_sql_comments를 사용하여 댓글을 절대적으로 활성화 해야하는 경우 :)

1.2에서 3.2로 업그레이드 할 때이 문제가 발생했습니다 (Big Jump Eh?).

내 경우의 문제는 HQL, 예를 들어 STRING HQL = "SELECT"...

SQL2005 방언을 사용하면 "System.notsupportedException : 쿼리는 'Select'... ..."메시지로 시작해야합니다.

해결책은해야합니다

  1. 실패한 단위 테스트를 만들고, 좋은 테스트 중심 개발자는 :)
  2. "Select ..."진술에서 선행 공간을 제거하십시오.
  3. 장치 테스트를 빌드하고 실행하십시오

내가 예측 한 것처럼 - 결합되지 않은 선택은 허용 가능한 해결 방법입니다.

삭제 SetMaxResults 그리고 그것은 작동합니다.

우리는 nhibernate 버전 3.3으로 업그레이드 할 때이 문제를 해결했지만 다른 이유가 있습니다 ... 공백. 우리는 다음과 같이 보이는 많은 SQL 문자열을 가지고있었습니다.

var sql = @"
select col1 from MyTable";

또는:

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

그 결과 nhibernate가 문자열을 검증하기 전에 문자열을 다듬지 않기 때문에 "쿼리는 'select'또는 'select'오류로 시작해야합니다.

우리는 이것을 먼저 줄이는 새로운 방언을 만들었습니다.

public class Sql2008DialectCustom : MsSql2008Dialect
{
  public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit)
  {
    var trimmedQueryString = queryString.Trim();
    return base.GetLimitString(trimmedQueryString, offset, limit);
  }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top