8

ビジネスフィルターの制約を表現できるようにするには、Criteria APIでyear()関数とmonth()関数を使用する必要があります。のような表現

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

明らかに機能しません-これを達成する方法はありますか?

HQLで完全に可能であることはわかっていますが、クエリを処理する追加のプロセスがいくつかあり、並べ替えやページングなどが追加されているため、条件APIを使用してクエリを作成する必要があります。


Criteria APIに書き直したいサンプルHQLソリューション:

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

3 に答える 3

8

Projections.SQLFunctionを使用してこれを実現することが可能です。実用的な解決策:

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));
于 2009-04-28T10:26:35.450 に答える
1

このようなものはあなたのために働きますか?

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

式の順序を変更したことに注意してください。タイプミスがあり、DateFromとDateToの間の日付を照会したいとします。日付に時刻データが含まれている場合、2番目の式は次のように変更されます。

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

ユーザーは「YYMM」の形式で入力していますか?その場合は、その文字列から年と月を解析して、fromYear、fromMonthなどを作成する必要があります。

編集:私の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));
于 2009-04-27T12:22:24.480 に答える
1

あなたの質問が何を意味するのか理解できませんが、同様の質問があり、次の方法で問題を解決しました。

crit.Add(Expression.Sql("(YEAR({alias}.ObsDatum) = ?)", year, NHibernateUtil.String))
crit.Add(Expression.Sql("(MONTH({alias}.ObsDatum) = ?)", manad, NHibernateUtil.Int32))
于 2009-06-10T05:44:41.327 に答える