NHibernate - 将DateTime转换为select内部的String抛出异常

时间:2016-08-05 20:57:23

标签: c# datetime nhibernate queryover

我正在使用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',但它未定义

我做错了什么?

1 个答案:

答案 0 :(得分:2)

TL; DR:NHibernate将QueryOver查询转换为SQL。它不知道如何将以下表达式转换为SQL:

Select(x => x.DateTime.ToString("dddd dd MMMM yyyy",ci))

这就是您收到错误的原因。您有几个选择:

  1. 对结果进行一些后处理以获得所需的日期格式。这是最简单的修复方法。你可以这样写:

    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) 
        });
    
  2. 编写一个自定义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函数,如果你对这条路线感兴趣的话。 (完全披露:这是我的个人博客)。