如何使用 NHibernate QueryOver 计算给定出生日期的年龄
How to Calculate Age given date of birth using NHibernate QueryOver
假设我有一个 class 如下:
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 扩展来实现这一点有什么建议吗?
以下是我一直在看的一些资料,但作为这方面的初学者,我很难把一些具体的东西放在一起。
http://www.andrewwhitaker.com/blog/2014/08/15/queryover-series-part-7-using-sql-functions/
经过一番努力,我能够制作出与我想要存档的内容类似的内容。
可能有更好的解决方案,但就目前而言,它按预期工作。
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;
}
}
假设我有一个 class 如下:
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 扩展来实现这一点有什么建议吗?
以下是我一直在看的一些资料,但作为这方面的初学者,我很难把一些具体的东西放在一起。
http://www.andrewwhitaker.com/blog/2014/08/15/queryover-series-part-7-using-sql-functions/
经过一番努力,我能够制作出与我想要存档的内容类似的内容。 可能有更好的解决方案,但就目前而言,它按预期工作。
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;
}
}