对于ICompositeUserType,如何在NHibernate ICriteria查询中比较使用.NET类型?

对于ICompositeUserType,如何在NHibernate ICriteria查询中比较使用.NET类型?,nhibernate,legacy,icriteria,compositeusertype,Nhibernate,Legacy,Icriteria,Compositeusertype,我回答了一个StackOverflow问题,关于如何将遗留的CHAR数据库日期和时间字段合并到我的POCO中的一个.NETDateTime属性中 (非常感谢!)。现在,我试图让一个定制的ICritera查询针对这个DateTime属性工作,但没有效果。我的问题是: ICriteria criteria = Session.CreateCriteria<InputFileLog>() .Add(Expression.Gt(MembersOf<InputFileLo

我回答了一个StackOverflow问题,关于如何将遗留的
CHAR
数据库日期和时间字段合并到我的POCO中的一个.NET
DateTime
属性中 (非常感谢!)。现在,我试图让一个定制的ICritera查询针对这个
DateTime
属性工作,但没有效果。我的问题是:

ICriteria criteria =
    Session.CreateCriteria<InputFileLog>()
    .Add(Expression.Gt(MembersOf<InputFileLog>.GetName(x => x.FileCreationDateTime), DateTime.Now.AddDays(-14)))
    .AddOrder(Order.Desc(Projections.Id()))
    .CreateCriteria(typeof(InputFile).Name)
        .Add(Expression.Eq(MembersOf<InputFile>.GetName(x => x.Id), inputFileName));

IList<InputFileLog> list = criteria.List<InputFileLog>();
实际上,这个查询正是我所期望的,只是它实际上没有给出我想要的(过去两周内的所有行),因为在DB中,它使用
CHAR
s而不是
DATE
s进行了大于的比较。我不知道如何让查询在不执行CreateSQLQuery()的情况下将
CHAR
值转换为查询中的
DATE
,我希望避免这样做。有人知道怎么做吗

更新: 我一直在尝试使用
Projections.SqlFunction()
或公式来实现这一点,但到目前为止没有任何效果。下面是我使用
SqlFunction()
得到的代码,但是我得到了一个
NHibernate.QueryException:property没有映射到单个列:FileCreationDateTime
错误:

DateTime twoWeeksAgo = DateTime.Now.AddDays(-14);
ICriteria criteria =
    Session.CreateCriteria<InputFileLog>()
    .Add(Restrictions.Gt(Projections.SqlFunction("to_date", NHibernateUtil.DateTime, Projections.Property(MembersOf<InputFileLog>.GetName(x => x.FileCreationDateTime))), twoWeeksAgo))
    //.Add(Expression.Gt(MembersOf<InputFileLog>.GetName(x => x.FileCreationDateTime), DateTime.Now.AddDays(-14)))
    .AddOrder(Order.Desc(Projections.Id()))
     .CreateCriteria(typeof(InputFile).Name)
        .Add(Expression.Eq(MembersOf<InputFile>.GetName(x => x.Id), inputFileName));
DateTime twoWeeksAgo=DateTime.Now.AddDays(-14);
ICriteria标准=
Session.CreateCriteria()
.Add(Restrictions.Gt(Projections.SqlFunction(“to_date”、NHibernateUtil.DateTime、Projections.Property(MembersOf.GetName(x=>x.FileCreationDateTime))),两周前)
//.Add(Expression.Gt(MembersOf.GetName(x=>x.FileCreationDateTime)、DateTime.Now.AddDays(-14)))
.AddOrder(Order.Desc(Projections.Id()))
.CreateCriteria(typeof(InputFile).Name)
.Add(Expression.Eq(MembersOf.GetName(x=>x.Id),inputFileName));

我确信我在这里做了一些错事,但它仍然不喜欢它,因为
FileCreationDateTime
使用了一个自定义的
ICompositeUserType
,它将.NET
DateTime
属性拆分为两个Oracle SQL
CHAR
列(有关详细信息,请参阅此StackOverflow)。

我终于找到了答案!下面是代码(出于某种原因,StackOverflow将第一个代码段中的一些方法名设置为类型的语法颜色):

我已经在
PropertyNames
成员实现中使用了
consts
数据库字段名
结构
,因此我也能够将这些硬编码的列名用于我需要的
投影

下面是通用的
到目前为止的
方法所使用的
投影
实用程序类:

public class ProjectionUtil
{
    public static IProjection GetToDateSQLProjection(
        string columnName, string dbToDateFormat, IType returnType)
    {
        return Projections.SqlProjection(
            string.Format("to_date({0}, '{1}') as {0}", columnName, dbToDateFormat),
            new string[] { columnName },
            new IType[] { returnType });
    }

    public static IProjection GetToDateSQLFunction(
        DateTime dt, string dotNetFormatString, string dbFormatString)
    {
        return Projections.SqlFunction(
            "to_date",
            NHibernateUtil.DateTime,
            Projections.Constant(dt.ToString(dotNetFormatString)),
            Projections.Constant(dbFormatString));
    }
}
最后,这里是NHibernate生成的Oracle SQL:

SELECT
    this_.input_file_token as input1_9_2_,
    this_.file_creation_date as file2_9_2_,
    this_.file_creation_time as file3_9_2_,
    this_.approval_ind as approval4_9_2_,
    this_.file_id as file5_9_2_,
    this_.process_name as process6_9_2_,
    this_.process_status as process7_9_2_,
    this_.input_file_name as input8_9_2_,
    gonogo3_.input_file_token as input1_6_0_,
    gonogo3_.go_nogo_ind as go2_6_0_,
    inputfile1_.input_file_name as input1_3_1_,
    inputfile1_.src_code as src2_3_1_,
    inputfile1_.process_cat_code as process3_3_1_
FROM
    input_file_log this_
    left outer join go_nogo gonogo3_ on this_.input_file_token=gonogo3_.input_file_token
    inner join input_file inputfile1_ on this_.input_file_name=inputfile1_.input_file_name
WHERE
    (
        to_date(file_creation_date, 'YYYYMMDD') > to_date(:p0, :p1) or 
        (
            to_date(file_creation_date, 'YYYYMMDD') = to_date(:p2, :p3) and
            to_date(file_creation_time, 'HH24:MI:SS') >= to_date(:p4, :p5)
        )
    ) and
    inputfile1_.input_file_name = :p6
ORDER BY this_.input_file_token desc;
:p0 = '20100415',
:p1 = 'YYYYMMDD',
:p2 = '20100415',
:p3 = 'YYYYMMDD',
:p4 = '18:48:48',
:p5 = 'HH24:MI:SS',
:p6 = 'LMCONV_JR'

真不敢相信我得到了这个!我想我肯定得求助于
ISQLQuery

我不能接受自己的答案是愚蠢的,因为事实上我在两周后就找到了答案,甚至没有其他人尝试过答案(或者对他们观点中的任何不明确之处发表评论)。我想我会删除这篇文章,尽管我认为这篇文章对一个晦涩难懂的NHibernate场景很有帮助。(很明显,我正试图通过这个评论得到一个反应)。
public class DefaultStringFileCreationDateTime : ICompositeUserType
{
    .
    .
    .
    public const string DotNetDateFormat = "yyyyMMdd";

    public const string DotNetTimeFormat = "HH:mm:ss";

    public const string DbDateFormat = "YYYYMMDD";

    public const string DbTimeFormat = "HH24:MI:SS";

    private const string _nullDateRepresentationInDb = "00000000";

    public struct DatabaseFieldNames
    {
        /// <summary>
        /// File creation date column name.
        /// </summary>
        public const string FileCreationDate = "file_creation_date";

        /// <summary>
        /// File creation time column name.
        /// </summary>
        public const string FileCreationTime = "file_creation_time";
    }

    public static IProjection GetFileCreationDateToDateSQLProjection()
    {
        return ProjectionUtil.GetToDateSQLProjection(DatabaseFieldNames.FileCreationDate, DbDateFormat, NHibernateUtil.DateTime);
    }

    public static IProjection GetFileCreationTimeToDateSQLProjection()
    {
        return ProjectionUtil.GetToDateSQLProjection(DatabaseFieldNames.FileCreationTime, DbTimeFormat, NHibernateUtil.DateTime);
    }

    public static IProjection GetFileCreationDateToDateSQLFunction(DateTime dt)
    {
        return ProjectionUtil.GetToDateSQLFunction(dt, DotNetDateFormat, DbDateFormat);
    }

    public static IProjection GetFileCreationTimeToDateSQLFunction(DateTime dt)
    {
        return ProjectionUtil.GetToDateSQLFunction(dt, DotNetTimeFormat, DbTimeFormat);
    }
}
public class ProjectionUtil
{
    public static IProjection GetToDateSQLProjection(
        string columnName, string dbToDateFormat, IType returnType)
    {
        return Projections.SqlProjection(
            string.Format("to_date({0}, '{1}') as {0}", columnName, dbToDateFormat),
            new string[] { columnName },
            new IType[] { returnType });
    }

    public static IProjection GetToDateSQLFunction(
        DateTime dt, string dotNetFormatString, string dbFormatString)
    {
        return Projections.SqlFunction(
            "to_date",
            NHibernateUtil.DateTime,
            Projections.Constant(dt.ToString(dotNetFormatString)),
            Projections.Constant(dbFormatString));
    }
}
SELECT
    this_.input_file_token as input1_9_2_,
    this_.file_creation_date as file2_9_2_,
    this_.file_creation_time as file3_9_2_,
    this_.approval_ind as approval4_9_2_,
    this_.file_id as file5_9_2_,
    this_.process_name as process6_9_2_,
    this_.process_status as process7_9_2_,
    this_.input_file_name as input8_9_2_,
    gonogo3_.input_file_token as input1_6_0_,
    gonogo3_.go_nogo_ind as go2_6_0_,
    inputfile1_.input_file_name as input1_3_1_,
    inputfile1_.src_code as src2_3_1_,
    inputfile1_.process_cat_code as process3_3_1_
FROM
    input_file_log this_
    left outer join go_nogo gonogo3_ on this_.input_file_token=gonogo3_.input_file_token
    inner join input_file inputfile1_ on this_.input_file_name=inputfile1_.input_file_name
WHERE
    (
        to_date(file_creation_date, 'YYYYMMDD') > to_date(:p0, :p1) or 
        (
            to_date(file_creation_date, 'YYYYMMDD') = to_date(:p2, :p3) and
            to_date(file_creation_time, 'HH24:MI:SS') >= to_date(:p4, :p5)
        )
    ) and
    inputfile1_.input_file_name = :p6
ORDER BY this_.input_file_token desc;
:p0 = '20100415',
:p1 = 'YYYYMMDD',
:p2 = '20100415',
:p3 = 'YYYYMMDD',
:p4 = '18:48:48',
:p5 = 'HH24:MI:SS',
:p6 = 'LMCONV_JR'