vistas vista vinculado ver varias usuarios usuario una tablas servidor parametros obtener definicion crear consulta conectados con actual sql-server nhibernate paging criteria projection

sql-server - vista - sql server ver usuarios conectados



Agregar una proyección a un criterio NHibernate le impide realizar la selección de entidad predeterminada (6)

Estoy escribiendo un criterio NHibernate que selecciona los datos que soportan la búsqueda. Estoy usando la expresión COUNT(*) OVER() de SQL Server 2005 (+) para obtener el número total de filas disponibles, como lo sugiere Ayende Rahien. Necesito ese número para poder calcular cuántas páginas hay en total. La belleza de esta solución es que no necesito ejecutar una segunda consulta para obtener el recuento de filas.

Sin embargo, parece que no logro escribir un criterio de trabajo (Ayende solo proporciona una consulta HQL).

Aquí hay una consulta SQL que muestra lo que quiero y funciona muy bien. Tenga en cuenta que intencionalmente omití la lógica de paginación real para enfocarme en el problema:

SELECT Items.*, COUNT(*) OVER() AS rowcount FROM Items

Aquí está el HQL:

select item, rowcount() from Item item

Tenga en cuenta que la función rowcount() está registrada en un dialecto NHibernate personalizado y se resuelve en COUNT(*) OVER() en SQL.

Un requisito es que la consulta se exprese utilizando un criterio. Lamentablemente, no sé cómo hacerlo bien:

var query = Session .CreateCriteria<Item>("item") .SetProjection( Projections.SqlFunction("rowcount", NHibernateUtil.Int32));

Cada vez que agrego una proyección, NHibernate no selecciona el item (como lo haría sin una proyección), solo el rowcount() mientras realmente necesito ambos. Además, parece que no puedo proyectar el item como un todo, solo sus propiedades y realmente no quiero enumerarlas todas.

Espero que alguien tenga una solución para esto. Gracias de cualquier manera.


Use CreateMultiCriteria.

Puede ejecutar 2 instrucciones simples con solo un hit al DB de esa manera.


Me pregunto por qué usar Criteria es un requisito. ¿No puedes usar session.CreateSQLQuery? Si realmente debe hacerlo en una consulta, le habría sugerido que retire los objetos Item y el recuento, como:

select {item.*}, count(*) over() from Item {item}

... de esta manera puede recuperar los objetos Item de su consulta, junto con el conteo. Si tiene un problema con el almacenamiento en caché de Hibernate, también puede configurar los espacios de consulta (cachés de entidades / tablas) asociados con una consulta nativa para que las entradas de caché de consultas antiguas se borren automáticamente.


Creo que no es posible en Criteria, tiene algunos límites.

Puede obtener la identificación y cargar elementos en una consulta posterior:

var query = Session .CreateCriteria<Item>("item") .SetProjection(Projections.ProjectionList() .Add(Projections.SqlFunction("rowcount", NHibernateUtil.Int32)) .Add(Projections.Id()));

Si no te gusta, usa HQL, puedes establecer la cantidad máxima de resultados allí también:

IList<Item> result = Session .CreateQuery("select item, rowcount() from item where ..." ) .SetMaxResult(100) .List<Item>();


Si entiendo tu pregunta correctamente, tengo una solución. Luché bastante con este mismo problema.

Permítanme describir rápidamente el problema que tuve, para asegurarme de que estamos en la misma página. Mi problema se redujo a paginación. Quiero mostrar 10 registros en la interfaz de usuario, pero también quiero saber el número total de registros que coinciden con los criterios de filtro. Quería lograr esto usando la API de criterios de NH, pero al agregar una proyección para el recuento de filas, mi consulta ya no funcionaba y no obtenía ningún resultado (no recuerdo el error específico, pero suena como lo que está recibiendo).

Aquí está mi solución (copiar y pegar desde mi código de producción actual). Tenga en cuenta que "SessionError" es el nombre de la entidad comercial para la que estoy recuperando los datos paginados, de acuerdo con el criterio de 3 filtros: IsDev, IsRead y IsResolved.

ICriteria crit = CurrentSession.CreateCriteria(typeof (SessionError)) .Add(Restrictions.Eq("WebApp", this)); if (isDev.HasValue) crit.Add(Restrictions.Eq("IsDev", isDev.Value)); if (isRead.HasValue) crit.Add(Restrictions.Eq("IsRead", isRead.Value)); if (isResolved.HasValue) crit.Add(Restrictions.Eq("IsResolved", isResolved.Value)); // Order by most recent crit.AddOrder(Order.Desc("DateCreated")); // Copy the ICriteria query to get a row count as well ICriteria critCount = CriteriaTransformer.Clone(crit) .SetProjection(Projections.RowCountInt64()); critCount.Orders.Clear(); // NOW add the paging vars to the original query crit = crit .SetMaxResults(pageSize) .SetFirstResult(pageNum_oneBased * pageSize); // Set up a multi criteria to get your data in a single trip to the database IMultiCriteria multCrit = CurrentSession.CreateMultiCriteria() .Add(crit) .Add(critCount); // Get the results IList results = multCrit.List(); List<SessionError> sessionErrors = new List<SessionError>(); foreach (SessionError sessErr in ((IList)results[0])) sessionErrors.Add(sessErr); numResults = (long)((IList)results[1])[0];

Entonces creo mi criterio base, con restricciones opcionales. Luego lo CLONE y agrego una proyección de recuento de filas a los criterios de CLONED. Tenga en cuenta que lo clono antes de agregar las restricciones de búsqueda. Luego configuré un IMultiCriteria para contener los objetos ICriteria originales y clonados, y uso el IMultiCriteria para ejecutarlos. Ahora tengo mis datos paginados del ICriteria original (y solo arrastré los datos que necesito a través del cable), y también un recuento bruto de cuántos registros reales coinciden con mis criterios (útiles para mostrar o crear enlaces de paginación, o lo que sea). Esta estrategia me ha funcionado bien. Espero que esto sea útil.


Sugiero que investigue el transformador de resultados personalizado llamando a SetResultTransformer () en su sesión.


Cree una propiedad de fórmula en la asignación de clase:

<property name="TotalRecords" formula="count(*) over()" type="Int32" not-null="true"/>; IList<...> result = criteria.SetFirstResult(skip).SetMaxResults(take).List<...>(); totalRecords = (result != null && result.Count > 0) ? result[0].TotalRecords : 0; return result;