2017-05-19 6 views
2

J'ai cette méthode QueryOver:NHibernate Query/QueryOver avec DateTime Comparaison

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

Actuellement, je filtrent ma collection en dehors de SQL. Pas si bon pour la performance.

Ma méthode IsRecentlyAccessed ressemble:

/// <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 ne supporte pas DateTime.Subtract ni poignée DateTime1 - DateTime2 très facilement.

J'ai regardé à travers les ressources en ligne et tout le monde semble suggérer trop complexe function expressions ou extension methods. Ces solutions semblent excessives quand tout ce qui m'intéresse est de soustraire une valeur.

N'y a-t-il pas des solutions simples? Une approche manuelle pour l'élaboration de la requête SQL semble être la meilleure solution, mais il est dommage que NHibernate soit stoppé dans ses pistes par quelque chose qui semble être trivial.

+0

Avez-vous essayé d'ajouter -1? – jdweng

Répondre

1

Qu'en est-ce qui suit?

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 sait comment comparer les dates. C'est le calcul de la date qui n'est pas supporté dans votre cas. En le déplaçant sur le paramètre, il a été évalué au moment de l'exécution au lieu d'essayer de le traduire en SQL.

Si vous souhaitez que les calculs de date soient traduits en SQL, reportez-vous à answer to another question.

0

La syntaxe est pas grand et cela prendra quelques ajustements, mais vous devriez être en mesure de faire quelque chose comme ça ...

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