我正在使用NHibernate,我有一个查询,我试图选择日期时间并将其转换为字符串:
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>();
引发以下异常:
从范围''引用的'Form2.Entities.Date'类型的变量'x',但它未定义
我做错了什么?
答案 0 :(得分:2)
TL; DR:NHibernate将QueryOver查询转换为SQL。它不知道如何将以下表达式转换为SQL:
Select(x => x.DateTime.ToString("dddd dd MMMM yyyy",ci))
这就是您收到错误的原因。您有几个选择:
对结果进行一些后处理以获得所需的日期格式。这是最简单的修复方法。你可以这样写:
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方言。此示例使用SQL Server 2014上提供的FORMAT
函数:
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函数,如果你对这条路线感兴趣的话。 (完全披露:这是我的个人博客)。