how to user year() and month() functions in NH Criteria API?

后端 未结 3 2036
轻奢々
轻奢々 2020-12-13 22:44

I need to use year() and month() functions in Criteria API to be able to express a business filter constrain. Expressions like

cri.Add(Expression.Ge(\"year(         


        
相关标签:
3条回答
  • 2020-12-13 23:08

    It's possible to achieve this using Projections.SQLFunction. Working solution:

    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));
    
    0 讨论(0)
  • 2020-12-13 23:12

    Would something like this work for you?

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

    Note that I changed your expression order -- I'm assuming you made a typo and you want to query for dates between DateFrom and DateTo. If the dates contain time data, the second expression would change to:

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

    In response to comment:

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

    Is your user input in the form "YYMM"? If that's the case, then you just have to parse out year and month from that string to create fromYear, fromMonth, etc.

    Edit: my 3rd and final attempt:

    // 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 讨论(0)
  • 2020-12-13 23:17

    I'm not sure I understod what you mean with your question but I had a similar question, and I solved the problem with:

    crit.Add(Expression.Sql("(YEAR({alias}.ObsDatum) = ?)", year, NHibernateUtil.String))
    crit.Add(Expression.Sql("(MONTH({alias}.ObsDatum) = ?)", manad, NHibernateUtil.Int32))
    
    0 讨论(0)
提交回复
热议问题