带有DateTime比较的NHibernate Query / QueryOver

时间:2017-05-19 00:29:47

标签: c# datetime nhibernate fluent-nhibernate

我有这个QueryOver方法:

public IEnumerable<TrackedReportData> GetUnused(TimeSpan cacheExpiration)
{
    return Session
        .QueryOver<TrackedReportData>()
        .Where(t => t.CacheSize > 0)
        // TODO: NHibernate doesn't support DateTime comparison out-of-box.
        //.Where(t => t.CacheSize > 0 && !t.IsRecentlyAccessed(cacheExpiration))
        .List()
        .Where(t => !t.IsRecentlyAccessed(cacheExpiration));
}

目前,我正在SQL之外过滤我的集合。表现不太好。

我的IsRecentlyAccessed方法如下:

/// <summary>
/// Returns true if the cacheMeta has been accessed within the last `cacheExpiration`
/// number of milliseconds.
/// </summary>
public bool IsRecentlyAccessed(TimeSpan cacheExpiration)
{
    if (!LastAccessDate.HasValue)
        return false;

    return DateTime.Now.Subtract(LastAccessDate.Value) <= cacheExpiration;
}

NHibernate不支持DateTime.Subtract,也不容易处理DateTime1 - DateTime2

我已经在线查看了资源,似乎每个人都建议过于复杂function expressionsextension methods。当我感兴趣的是减去一个值时,这些解决方案似乎有些过分。

有没有简单的解决方案?制作SQL查询的手动方法似乎是最好的选择,但令人遗憾的是NHibernate已经停止了 这似乎是微不足道的。

2 个答案:

答案 0 :(得分:2)

以下情况如何?

public IEnumerable<TrackedReportData> GetUnused(TimeSpan cacheExpiration)
{
    return Session
        .QueryOver<TrackedReportData>()
        .Where(t => t.CacheSize > 0)
        .Where(Restrictions.Or(
            Restrictions.On<TrackedReportData>(t => t.LastAccessDate).IsNull,
            Restrictions.Where<TrackedReportData>(
                t => t.LastAccessDate < DateTime.Now.Add(-cacheExpiration))))
        .List();
}

NHibernate知道如何比较日期。这是您的案例中不支持的日期计算。在参数上移动它会导致在运行时对其进行评估,而不是尝试将其转换为SQL。

如果您希望将日期计算转换为SQL,请参阅此answer to another question

答案 1 :(得分:0)

语法不是很好,这需要一些调整,但你应该可以做这样的事情......

return Session
    .QueryOver<TrackedReportData>()
    .Where(t => t.CacheSize > 0)
    .Where(
        Restrictions.Lte(
            Projections.SqlFunction(
                new VarArgsSQLFunction("(", "-", ")"),
                NHibernateUtil.DateTime,
                Projections.Property(t => t.LastAccessDate),
                Projections.Constant(DateTime.Now)),
            cacheExpiration);