2009-04-27 8 views
8

Necesito usar las funciones year() y month() en Criteria API para poder expresar una restricción de filtro empresarial. Expresiones comocómo usar las funciones de año() y mes() en NH Criteria API?

cri.Add(Expression.Ge("year(Duration.DateFrom)", Year.Value)); 
cri.Add(Expression.Le("year(Duration.DateTo)", Year.Value)); 

obviamente no funcionan - ¿hay alguna solución para lograr esto?

Sé que es totalmente posible en HQL, pero necesito construir la consulta utilizando los criterios del API, porque hay algunos procesos adicionales de procesamiento de la consulta adición de clasificación, paginación, etc ..


solución de muestra que HQL me gustaría volver a escribir a los criterios del API:

var ym = year * 100 + month; 
var hql = ...(:ym between 100 * year(f.Duration.DateFrom) + month(f.Duration.DateFrom) and 100 * year(f.Duration.DateTo) + month(f.Duration.DateTo)"; 

Respuesta

8

Es posible lograr este usando Projections.SQLFunction. Solución de trabajo:

ISQLFunction sqlAdd = new VarArgsSQLFunction("(", "+", ")"); 
ISQLFunction sqlMultiply = new VarArgsSQLFunction("(", "*", ")"); 

var ym = Year.Value * 100 + Month.Value; 
var dateFromMonthProj = Projections.SqlFunction("month", NHibernateUtil.Int32, Projections.Property("PurchaseDuration.DateFrom")); 
var dateFromYearProj = Projections.SqlFunction("year", NHibernateUtil.Int32, Projections.Property("PurchaseDuration.DateFrom")); 
var dateToMonthProj = Projections.SqlFunction("month", NHibernateUtil.Int32, Projections.Property("PurchaseDuration.DateTo")); 
var dateToYearProj = Projections.SqlFunction("year", NHibernateUtil.Int32, Projections.Property("PurchaseDuration.DateTo")); 
var calculatedYMFrom = Projections.SqlFunction(sqlAdd, NHibernateUtil.Int32, Projections.SqlFunction(sqlMultiply, NHibernateUtil.Int32, dateFromYearProj, Projections.Constant(100)), dateFromMonthProj); 
var calculatedYMTo = Projections.SqlFunction(sqlAdd, NHibernateUtil.Int32, Projections.SqlFunction(sqlMultiply, NHibernateUtil.Int32, dateToYearProj, Projections.Constant(100)), dateToMonthProj); 
cri.Add(Restrictions.Le(calculatedYMFrom, ym)); 
cri.Add(Restrictions.Ge(calculatedYMTo, ym)); 
1

¿Podría algo así como este trabajo para usted?

cri.Add(Expression.Ge("Duration.DateFrom", new Date(fromYear, 1, 1)); 
cri.Add(Expression.Le("Duration.DateTo", new Date(toYear, 12, 31)); 

Tenga en cuenta que he cambiado su pedido expresión - Estoy asumiendo que cometió un error tipográfico y que desea consultar para fechas entre dateFrom y dateTo. Si las fechas contienen datos de tiempo, la segunda expresión cambiará a:

cri.Add(Expression.Lt("Duration.DateTo", new Date(toYear + 1, 1, 1)); 

En respuesta al comentario:

cri.Add(Expression.Ge("Duration.DateFrom", new Date(fromYear, fromMonth, 1)); 
// Actual code needs to get last day of to month since it will not always be 31 
cri.Add(Expression.Le("Duration.DateTo", new Date(toYear, toMonth, 31)); 

Está su entrada del usuario en la forma "AAMM"? Si ese es el caso, entonces sólo hay que analizar el año y el mes de esa cadena para crear fromYear, fromMonth, etc.

Editar: mi tercero y último intento:

// First parse the input, e.g: september 2009 into 9 (inMonth) and 2009 (inYear) 
var fromDate = new DateTime(inYear, inMonth, 1); 
var toDate = fromDate.AddMonths(1).AddDays(-1); 

cri.Add(Expression.Ge("Duration.DateFrom", fromDate)); 
cri.Add(Expression.Le("Duration.DateTo", toDate)); 
+0

Esto, desafortunadamente, no es suficiente. La entrada del usuario es año + mes y necesito devolver todos los objetos con Duración intersectando el año + mes. La solución similar en HQL se ve así: var ym = year * 100+ month; var hql = ... (: ym entre 100 * año (f.Duration.DateFrom) + mes (f.Duration.DateFrom) y 100 * año (f.Duration.DateTo) + mes (f.Duration.DateTo) "; No puedo averiguar cómo crear la misma consulta usando la API de Criteria – Buthrakaur

+0

en respuesta a la edición: Tengo una combinación de un año y un mes. La historia del usuario es como:" muéstrame objetos con duración que cubre septiembre de 2009 ". Puedo tener el objeto {DateFrom = new DateTime (2008,1,1), DateTo = new DateTime (2222, 1, 2)} y la entrada del usuario es" septiembre de 2009 "- su sugerencia no funciona aquí . – Buthrakaur

0

No estoy seguro de que understod lo que quiere decir con su pregunta, pero yo tenía una pregunta similar, y resuelto el problema:

crit.Add(Expression.Sql("(YEAR({alias}.ObsDatum) = ?)", year, NHibernateUtil.String)) 
crit.Add(Expression.Sql("(MONTH({alias}.ObsDatum) = ?)", manad, NHibernateUtil.Int32)) 
Cuestiones relacionadas