1

Допустим, у меня есть класс следующим образом:Как рассчитать Возраст данную дату рождения с помощью NHibernate QueryOver

public class Person 
{ 
    public int PersonId {get; set;} 
    public string Firstame {get; set;} 
    public string Lastname {get; set;} 
    public datetime Birthdate {get; set;} 
} 

Тогда TSQL как:

select (Firstname + ' ' + Lastname) as Name, 
    Birthdate, 
    case 
     when (month(cast(Birthdate as date)) > month(getdate()) 
     or (day(cast(Birthdate as date)) > day(getdate()) and month(cast(Birthdate as date)) = month(getdate()))) 
      then datediff(year, cast(Birthdate as date), getdate())-1 
     else datediff(year,cast(Birthdate as date), getdate()) 
    end as Age 
from Person 
go 

Я новичок в NHibernate и QueryOver и я пытались придумать способ перевести следующее в QueryOver.

case 
    when (month(cast(Birthdate as date)) > month(getdate()) 
    or (day(cast(Birthdate as date)) > day(getdate()) and month(cast(Birthdate as date)) = month(getdate()))) 
     then datediff(year, cast(Birthdate as date), getdate())-1 
    else datediff(year,cast(Birthdate as date), getdate()) 
end as Age 

Любые предложения о том, как это можно достичь с помощью QueryOver или даже лучше в качестве расширения IProjection?

Ниже перечислены некоторые материалы, на которые я смотрел, но, будучи новичком в этом, мне трудно помещать что-то совместное.

NHibernate QueryOver CASE WHEN calculate on column value

http://www.andrewwhitaker.com/blog/2014/08/15/queryover-series-part-7-using-sql-functions/

ответ

1

После немного борьбы, я был в состоянии приготовить что-то похожее на то, что я искал в архив. Там могут быть лучшие решения, но пока это работает так, как ожидалось.

public IQueryOver<Person> GetQuery(ISession session) 
{ 
    Person person = null; 

    DateTime? endDate = DateTime.Today; 

    SomePersonView dto = null; 

    IProjection birthDate = Projections.Conditional(
     Restrictions.IsNull(Projections.Property(() => person.BirthDate)), 
     Projections.Constant(endDate, NHibernateUtil.DateTime), 
     Projections.Property(() => person.BirthDate)); 

    var personQuery = session.QueryOver<Person>(() => person) 
     .Select(
      Projections.Distinct(
       Projections.ProjectionList() 
        .Add(Projections.SqlFunction("concat", 
          NHibernateUtil.String, 
          Projections.Property(() => person.FirstName), 
          Projections.Constant(" "), 
          Projections.Property(() => person.LastName)).WithAlias(() => dto.Name)) 
        .Add(Projections.Property(() => person.BirthDate).WithAlias(() => dto.BirthDate)) 
        .Add(DateProjections.Age("yy", birthDate, endDate).WithAlias(() => dto.Age)))) 
     .TransformUsing(Transformers.AliasToBean<SomePersonView>()); 

    return personQuery; 
} 

А вот расширение, где 'DateProjections.Age' приходит.

public static class DateProjections 
{ 
    private const string DateDiffFormat = "datediff({0}, ?1, ?2)"; 

    // Maps datepart to an ISQLFunction 
    private static Dictionary<string, ISQLFunction> DateDiffFunctionCache = new Dictionary<string, ISQLFunction>(); 

    public static IProjection DateDiff(string datepart, IProjection startDate, DateTime? endDate) 
    { 
     ISQLFunction sqlFunction = GetDateDiffFunction(datepart); 

     return Projections.SqlFunction(
      sqlFunction, 
      NHibernateUtil.Int32, 
      startDate, 
      Projections.Constant(endDate)); 
    } 

    //Get exact age of a person as of today 
    public static IProjection Age(string datepart, IProjection startDate, DateTime? endDate) 
    { 
     IProjection myAge = DateDiff("yy", 
      startDate, endDate); 

     IProjection ageMinusOne = Projections.SqlFunction(
      new VarArgsSQLFunction("(", "-", ")"), NHibernateUtil.Int32, myAge, 
      Projections.Constant(1)); 

     IProjection datePartMonthBirthdate = Projections.SqlFunction("month", NHibernateUtil.Int32, 
      startDate); 

     IProjection datePartDayBirthdate = Projections.SqlFunction("day", NHibernateUtil.Int32, 
      startDate); 

     IProjection datePartMonthCurrentDate = Projections.SqlFunction("month", NHibernateUtil.Int32, 
      Projections.Constant(endDate)); 

     IProjection datePartDayCurrentDate = Projections.SqlFunction("day", NHibernateUtil.Int32, 
      Projections.Constant(endDate)); 

     IProjection myRealAge = Projections.Conditional(
           Restrictions.Or(
            Restrictions.GtProperty(datePartMonthBirthdate, datePartMonthCurrentDate), 
            Restrictions.GtProperty(datePartDayBirthdate, datePartDayCurrentDate) 
            && Restrictions.EqProperty(datePartMonthBirthdate, datePartMonthCurrentDate)), 
           ageMinusOne, 
           myAge); 
     return myRealAge; 
    } 

    private static ISQLFunction GetDateDiffFunction(string datepart) 
    { 
     ISQLFunction sqlFunction; 

     if (!DateDiffFunctionCache.TryGetValue(datepart, out sqlFunction)) 
     { 
      string functionTemplate = string.Format(DateDiffFormat, datepart); 
      sqlFunction = new SQLFunctionTemplate(NHibernateUtil.Int32, functionTemplate); 

      DateDiffFunctionCache[datepart] = sqlFunction; 
     } 
     return sqlFunction; 
    } 
} 
+0

Рад, что вы это поняли! –

Смежные вопросы