2017-05-19 2 views
2

Ich habe diese QueryOver Methode:NHibernate Query/QueryOver mit Datetime-Vergleich

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)); 
} 

Derzeit bin ich Filterung meiner Sammlung außerhalb von SQL. Nicht so gut für die Leistung.

Meine IsRecentlyAccessed Methode wie folgt aussieht:

/// <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 nicht DateTime.Subtract unterstützt noch sie DateTime1 - DateTime2 sehr leicht umgehen kann.

Ich habe durch Ressourcen online geschaut und jeder scheint übermäßig komplex function expressions oder extension methods vorzuschlagen. Diese Lösungen scheinen übertrieben, wenn ich nur einen Wert subtrahieren möchte.

Gibt es keine einfachen Lösungen? Ein manueller Ansatz zur Erstellung der SQL-Abfrage scheint die beste Wette zu sein, aber es ist eine Schande, dass NHibernate in seinen Tracks von etwas gestoppt wird, was als trivial erscheint.

+0

Haben Sie versucht, -1 hinzuzufügen? – jdweng

Antwort

1

Was ist mit den folgenden?

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 kann Daten vergleichen. Das ist die Datumsberechnung, die in Ihrem Fall nicht unterstützt wird. Wenn Sie den Parameter verschieben, wird er zur Laufzeit ausgewertet, anstatt zu versuchen, ihn in SQL zu übersetzen.

Wenn Sie möchten, dass Datumsberechnungen in SQL übersetzt werden, lesen Sie answer to another question.

0

Die Syntax ist nicht groß, und dies wird einige Optimierungen nehmen, aber man sollte etwas sein können, wie dies zu tun ...

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);