按当地日期分组

时间:2014-02-27 11:35:53

标签: nhibernate

我的场景: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

1 个答案:

答案 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[]>();

同时检查: