我的场景:NHibernate用于填充位于网页上的某些网格。数据库是Ms SqlServer 2008/2012,未来几年不会更改。我需要按DateTime列分组行(以UTC格式存储为Sql日期时间类型),但仅限日期部分。此外,由于客户可以有不同的时区,我需要按日期对具有偏移量进行分组。选择是这样的:
SELECT
CAST(CONVERT(char(8),
[dbo].fn_LocalDayFromUTCDate(
this_.datetime1 /* this is CreationTime property mapped by NHibernate to column datetime1 */,
-240 /* hour offset and some other TimeZone params */),
112 /* timestyle */) AS datetime) as _date
FROM SomeTable as this_
GROUP BY CAST(CONVERT(char(8),
[dbo].fn_LocalDayFromUTCDate(this_.datetime1, -240),112) AS datetime)
已更新 在Radim的回答中,我确实设法用自定义sql函数注册自定义方言,如下所示:
public class CustomMsSql2008Dialect : MsSql2008Dialect
{
public CustomMsSql2008Dialect()
{
RegisterFunction(
"toLocalTime",
new SQLFunctionTemplate(
NHibernateUtil.UtcDateTime,
"CAST(CONVERT(char(8), [dbo].fn_LocalDayFromUTCDate(?1, ?2),112) AS datetime)"));
}
}
public static class CustomProjections
{
public static IProjection LocalDate(IProjection datePropertyProjection, int offsetInMinutes)
{
return Projections.SqlFunction(
"toLocalTime",
NHibernateUtil.UtcDateTime,
datePropertyProjection,
Projections.Constant(offsetInMinutes));
}
}
我能够像这样使用:
var groupProjection = Projections.GroupProperty(
CustomProjections.LocalDate(
Projections.Property("CreationTime"),
-240));
问题是,它生成了缺少第二个参数的GROUP BY
部分:
SELECT CAST(CONVERT(char(8), [dbo].fn_LocalDayFromUTCDate(this_.datetime1, @p1),112) AS datetime) as y1_
FROM SomeTable this_
GROUP BY CAST(CONVERT(char(8), [dbo].fn_LocalDayFromUTCDate(this_.datetime1, ?),112) AS datetime)
ORDER BY y1_ asc
答案 0 :(得分:1)
将上述SELECT和GROUP BY直接转换为SqlGroupProjection
可能是这样的:
var criteria = session.CreateCriteria<SomeEntity>(); // mapped to SomeTable
criteria.SetProjection(
Projections.ProjectionList()
.Add(
Projections.SqlGroupProjection(
" CAST(CONVERT(char(8), " +
" [dbo].fn_LocalDayFromUTCDate( " +
" this_.datetime1 /* this must be mapped by NHibernate column */, " +
" -240 /* hour offset and some other TimeZone params */), " +
" 112 /* timestyle */) AS datetime) ",
" CAST(CONVERT(char(8), " +
" [dbo].fn_LocalDayFromUTCDate(this_.datetime1, -240),112) AS datetime)",
new string[] {}, // could be empty, while not used for
new IType[] {} // transformation
)
));
var list = criteria.List<object[]>();
同时检查: