saber junta general estado esta consulta como becas beca andalucĂ­a andalucia aceptada nhibernate second-level-cache

nhibernate - general - junta de andalucia becas



NHibernate 2nd lvl cache, consulta personalizada, sqldialect (7)

Repare el error usando la solución de Alkampfer, pero creé mi propio dialecto SQL en lugar de aplicar parches a la fuente de NHibernate directamente:

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

Tengo la versión troncal de NH y FNH. Cuando intento agregar caché de segundo nivel, algunas partes de NHibernate olvidan el sqldialect elegido.

Configuracion inicial:

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

Consulta personalizada culpable:

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();

Cuando cambio la configuración a:

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

Error de arrojar consultas (se agregó la cláusula WITH en mssql2008):

La consulta debería comenzar con ''SELECT'' o ''SELECT DISTINCT''

[NotSupportedException: la consulta debería comenzar con ''SELECT'' o ''SELECT DISTINCT''] NHibernate.Dialect.MsSql2000Dialect.GetAfterSelectInsertPoint (SqlString sql) +179 NHibernate.Dialect.MsSql2000Dialect.GetLimitString (SqlString querySqlString, Int32 offset, Int32 limit) +119 NHibernate .Dialect.MsSql2005Dialect.GetLimitString (SqlString querySqlString, Int32 offset, Int32 last) +127 NHibernate.Loader.Loader.PrepareQueryCommand (QueryParameters queryParameters, Boolean scroll, ISessionImplementor session) +725 NHibernate.Loader.Loader.DoQuery (sesión de ISessionImplementor, QueryParameters queryParameters , Boolean returnProxies) +352 NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections (sesión de ISessionImplementor, QueryParameters queryParameters, Boolean returnProxies) +114 NHibernate.Loader.Loader.DoList (sesión de ISessionImplementor, QueryParameters queryParameters) +205

¿Alguna idea de qué es exactamente lo que confunde a nhibernate y cómo solucionarlo?

Código de NHibernate culpable (en NHibernate / Dialect / 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''"); } }

Parece que .SetMaxResults(123) causa esto. Afortunadamente, puedo desatar esa consulta.

Espero que eso arregle esto.


Tal como predije, la selección de unbounding es una solución aceptable.

Se SetMaxResults y funciona.


Simplemente tuve el mismo problema al utilizar una consulta similar que tiene una cláusula WITH.

Desafortunadamente, mi consulta rellena una grilla, con paginación, así que tengo que mantener SetMaxResults.

Mi solución fue reescribir usando una tabla derivada:

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

se convierte

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

Solo para permitir que NHibernate inserte la cadena "TOP x" después de la cadena "seleccionar" (6 caracteres desde el principio) ... Sin comentarios :(

T


Tuve un problema similar (la eliminación de SetMaxResults también me ayudó pero necesitaba paginación) y descubrí que la siguiente propiedad de configuración de NHibernate estaba causando este error:

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

Sin duda es un error, porque el método GetAfterSelectInsertPoint no tiene en cuenta que los comentarios de SQL pueden anteponerse a la consulta SQL.

Simplemente establezca la propiedad use_sql_comments en false y el problema desaparece.


Parece que hay algún error extraño en la rutina utilizada para encontrar el lugar en la consulta para insertar la cláusula TOP (GetAfterSelectInsertPoint) tal como lo dice Sandor. Puedes arreglarlo directamente en nh source (de hecho, parché la versión 2.1 que estoy usando en un proyecto, puedes encontrar detalles aquí ). Entonces, si necesitas habilitar los comentarios con use_sql_comments, puedes :)


Encontré este problema al actualizar de 1.2 a 3.2 (lo sé, GRAN salto ¿eh?).

El problema en mi caso fue que hay un espacio principal delante de la declaración de selección en el hql, por ejemplo, String hql = "select" ...

Con SQL2005 Dialect, esto se bloquea con una "System.NotSupportedException: la consulta debería comenzar con el mensaje ''SELECT'' ...".

La solución es

  1. cree una prueba unitaria que falle, un buen desarrollador impulsado por prueba debería :)
  2. eliminar el espacio inicial de la declaración "seleccionar ..."
  3. construir y ejecutar la prueba unitaria

Nos encontramos con este problema al actualizar a NHibernate versión 3.3, pero por una razón diferente ... espacios en blanco. Teníamos muchas cadenas sql que se veían así:

var sql = @" select col1 from MyTable";

o:

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

Como resultado, "La consulta debería comenzar con los errores ''SELECCIONAR'' o ''SELECCIONAR DISTINCIÓN''" porque NHibernate no recorta la cadena antes de validarla.

Creamos un nuevo dialecto que recorta la cuerda primero para evitar esto:

public class Sql2008DialectCustom : MsSql2008Dialect { public override SqlString GetLimitString(SqlString queryString, SqlString offset, SqlString limit) { var trimmedQueryString = queryString.Trim(); return base.GetLimitString(trimmedQueryString, offset, limit); } }