NHibernate - 在 select 内将 DateTime 转换为 String 抛出异常
NHibernate - Converting DateTime to String inside select throws exception
我正在使用 NHibernate,我有一个查询,我在其中尝试 select 日期时间并将其转换为字符串:
DateDTO dateDto = null;
CultureInfo ci = CultureInfo.CreateSpecificCulture("he-IL");
var dates = _session.QueryOver<Date>()
.Where(x => x.Client.Id == clientId)
.Where(x => x.IsVisible != 0)
.SelectList(lst => lst
.Select(x => x.Id).WithAlias(() => dateDto.Id)
.Select(x => x.DateTime.ToString("dddd dd MMMM yyyy",ci)).WithAlias(() => dateDto.Date))
.TransformUsing(Transformers.AliasToBean<DateDTO>())
.List<DateDTO>();
抛出以下异常:
variable 'x' of type 'Form2.Entities.Date' referenced from scope '', but it is not defined
我做错了什么?
TL;DR:NHibernate 将 QueryOver 查询转换为 SQL。它不知道如何将以下表达式转换为 SQL:
Select(x => x.DateTime.ToString("dddd dd MMMM yyyy",ci))
这就是您收到错误的原因。您有几个选择:
对结果进行一些 post 处理以获得所需的日期格式。这是最简单的修复方法。你可以这样写:
var dates = session.QueryOver<Date>()
.Where(x => x.IsVisible != 0)
.SelectList(lst => lst
.Select(x => x.Id)
.Select(x => x.DateTime))
.List<object[]>()
.Select(o => new DateDTO
{
Id = (int)o[0],
Date = ((DateTime)o[1]).ToString("dddd dd MMMM yyyy", ci)
});
编写一个自定义 SQL 函数来格式化数据库端的日期。 这需要多做一些工作,但最终结果可能看起来干净一点。此实现将取决于您的 SQL 方言。此示例使用 FORMAT
函数,在 SQL Server 2014 上可用:
ISQLFunction formatFunction =
new SQLFunctionTemplate(NHibernateUtil.String, "FORMAT(?1, 'dddd dd MMM yyy', 'he-IL')");
DateDTO dateDto = null;
session.QueryOver<Date>()
.Where(x => x.IsVisible != 0)
.SelectList(lst => lst
.Select(x => x.Id).WithAlias(() => dateDto.Id)
.Select(Projections.SqlFunction(
formatFunction,
NHibernateUtil.String,
Projections.Property<Date>(x => x.DateTime))
).WithAlias(() => dateDto.Date))
.TransformUsing(Transformers.AliasToBean<DateDTO>())
.List<DateDTO>()
.Dump();
这会生成以下内容 SQL:
SELECT
this_.Id as y0_,
FORMAT(this_.DateTime, 'dddd dd MMM yyy', 'he-IL') as y1_
FROM
Date this_
WHERE
not (this_.IsVisible = @p0);
如果您使用的 NHibernate 方言已经支持自定义函数,您甚至可能不需要创建自定义函数。
我有一个 blog post 关于在您的查询中使用 SQL 函数,如果您有兴趣的话。 (完全公开:这是我的个人博客)。
我正在使用 NHibernate,我有一个查询,我在其中尝试 select 日期时间并将其转换为字符串:
DateDTO dateDto = null;
CultureInfo ci = CultureInfo.CreateSpecificCulture("he-IL");
var dates = _session.QueryOver<Date>()
.Where(x => x.Client.Id == clientId)
.Where(x => x.IsVisible != 0)
.SelectList(lst => lst
.Select(x => x.Id).WithAlias(() => dateDto.Id)
.Select(x => x.DateTime.ToString("dddd dd MMMM yyyy",ci)).WithAlias(() => dateDto.Date))
.TransformUsing(Transformers.AliasToBean<DateDTO>())
.List<DateDTO>();
抛出以下异常:
variable 'x' of type 'Form2.Entities.Date' referenced from scope '', but it is not defined
我做错了什么?
TL;DR:NHibernate 将 QueryOver 查询转换为 SQL。它不知道如何将以下表达式转换为 SQL:
Select(x => x.DateTime.ToString("dddd dd MMMM yyyy",ci))
这就是您收到错误的原因。您有几个选择:
对结果进行一些 post 处理以获得所需的日期格式。这是最简单的修复方法。你可以这样写:
var dates = session.QueryOver<Date>() .Where(x => x.IsVisible != 0) .SelectList(lst => lst .Select(x => x.Id) .Select(x => x.DateTime)) .List<object[]>() .Select(o => new DateDTO { Id = (int)o[0], Date = ((DateTime)o[1]).ToString("dddd dd MMMM yyyy", ci) });
编写一个自定义 SQL 函数来格式化数据库端的日期。 这需要多做一些工作,但最终结果可能看起来干净一点。此实现将取决于您的 SQL 方言。此示例使用
FORMAT
函数,在 SQL Server 2014 上可用:ISQLFunction formatFunction = new SQLFunctionTemplate(NHibernateUtil.String, "FORMAT(?1, 'dddd dd MMM yyy', 'he-IL')"); DateDTO dateDto = null; session.QueryOver<Date>() .Where(x => x.IsVisible != 0) .SelectList(lst => lst .Select(x => x.Id).WithAlias(() => dateDto.Id) .Select(Projections.SqlFunction( formatFunction, NHibernateUtil.String, Projections.Property<Date>(x => x.DateTime)) ).WithAlias(() => dateDto.Date)) .TransformUsing(Transformers.AliasToBean<DateDTO>()) .List<DateDTO>() .Dump();
这会生成以下内容 SQL:
SELECT this_.Id as y0_, FORMAT(this_.DateTime, 'dddd dd MMM yyy', 'he-IL') as y1_ FROM Date this_ WHERE not (this_.IsVisible = @p0);
如果您使用的 NHibernate 方言已经支持自定义函数,您甚至可能不需要创建自定义函数。
我有一个 blog post 关于在您的查询中使用 SQL 函数,如果您有兴趣的话。 (完全公开:这是我的个人博客)。