Nhibernate 按本地日期分组

Nhibernate 按本地日期分组,nhibernate,Nhibernate,我的场景:NHibernate用于填充一些位于web页面上的网格。数据库为Ms SqlServer 2008/2012,在未来一年内不会更改。我需要按DateTime列(在UTC中存储为Sql DateTime类型)对行进行分组,但只能按日期部分进行分组。此外,由于客户端可以有不同的时区,我需要按有偏移量的日期分组。选择如下: SELECT CAST(CONVERT(char(8), [dbo].fn_LocalDayFromUTCDate( th

我的场景:NHibernate用于填充一些位于web页面上的网格。数据库为Ms SqlServer 2008/2012,在未来一年内不会更改。我需要按DateTime列(在UTC中存储为Sql DateTime类型)对行进行分组,但只能按日期部分进行分组。此外,由于客户端可以有不同的时区,我需要按有偏移量的日期分组。选择如下:

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)
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));
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[]>();
已更新 根据Radim的回答,我确实成功地用自定义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)
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));
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[]>();
我可以这样使用:

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)
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));
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[]>();
问题是,它正在生成缺少第二个参数的
分组依据
部件:

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

将上述SELECT和GROUP BY直接转换为
SqlGroupProjection
,可以如下所示:

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)
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));
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[]>();
var-criteria=session.CreateCriteria();//映射到某个表
标准.SetProjection(
投影。投影列表()
.添加(
Projections.SqlGroupProjection(
“转换(字符(8),”+
“[dbo].fn\u LocalDayFromUTCDate(”+
“this_uu.datetime1/*这必须由NHibernate列*映射”+
“-240/*小时偏移量和一些其他时区参数*/),”+
“112/*时间样式*/)作为日期时间)”,
“转换(字符(8),”+
“[dbo].fn_LocalDayFromUTCDate(this_u.datetime1,-240),112)作为datetime)”,
新字符串[]{},//可以为空,但不能用于
新的IType[]{}//转换
)
));
var list=criteria.list();
同时检查:


谢谢你,拉迪姆,我是从这里来的,现在我已经准备好了:如何用一个
Projections.Property(myGroupPropertyAlias)
替换具体的列名
this.\datetime1
,让NHbm为我生成它?我想,我们在这里唯一能做的就是用
{alias}
替换this.\uu。之后将由NHibernate取代。另一个选择是使用新的SQL函数扩展方言。它以后可以与属性投影一起使用。此处可以找到一个示例:。请检查这一点,因为在您的情况下,这将是最合适和最易于维护的