как использовать функции year () и month () в API NH Criteria? - PullRequest
8 голосов
/ 27 апреля 2009

Мне нужно использовать функции year () и month () в Criteria API, чтобы иметь возможность выражать ограничения бизнес-фильтра. Выражения типа

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

явно не работают - есть ли решение, как этого добиться?

Я знаю, что это вполне возможно в HQL, но мне нужно построить запрос с использованием API критериев, потому что есть некоторые дополнительные процессы, обрабатывающие запрос, добавляющие сортировку, разбиение на страницы и т. Д.


пример решения HQL, которое я хотел бы переписать в Criteria 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)";

Ответы [ 3 ]

8 голосов
/ 28 апреля 2009

Этого можно добиться с помощью функции Projection.SQL. Рабочий раствор:

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 голос
/ 27 апреля 2009

Хотелось бы что-нибудь подобное для вас?

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

Обратите внимание, что я изменил ваш порядок выражений - я предполагаю, что вы сделали опечатку и хотите запросить даты между DateFrom и DateTo. Если даты содержат данные о времени, второе выражение изменится на:

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

В ответ на комментарий:

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

Ваш пользователь вводит данные в форме "ГГММ"? Если это так, то вам просто нужно проанализировать год и месяц из этой строки, чтобы создать из года, месяца и т. Д.

Редактировать: моя 3-я и последняя попытка:

// 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 голосов
/ 10 июня 2009

Я не уверен, что понял, что вы имеете в виду под своим вопросом, но у меня был похожий вопрос, и я решил проблему с:

crit.Add(Expression.Sql("(YEAR({alias}.ObsDatum) = ?)", year, NHibernateUtil.String))
crit.Add(Expression.Sql("(MONTH({alias}.ObsDatum) = ?)", manad, NHibernateUtil.Int32))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...