NHibernate 3.0: ¿No hay FirstOrDefault () con QueryOver?


Estoy jugando con FluentNHibernate y NH 3.0, usando el proveedor LINQ y la nueva sintaxis QueryOver.

Ahora con QueryOver quiero obtener un elemento (llamado resultado) con un valor de marca de tiempo lo más cercano posible a un valor dado, pero no mayor:

 Result precedingOrMatchingResult = Session.QueryOver<Result>().
        Where(r => r.TimeStamp < timeStamp).
        OrderBy(r => r.TimeStamp).Desc.                
        FirstOrDefault(); //get the preceding or matching result, if there is any

Ahora, Intellisense me dice que no hay tal cosa como un método FirstOrDefault(). Por supuesto, podría enumerar mi consulta ordenada y luego usar LINQ para obtener mi artículo. Pero esto cargaría todos los elementos en la memoria primero.

Hay una alternativa a FirstOrDefault(), o he entendido algo completamente equivocado?

Author: Marcel, 2010-12-29

4 answers

NH 3 tiene un proveedor LINQ integrado (las consultas se traducen internamente a HQL/SQL). Tienes que añadir el NHibernate.Espacio de nombres Linq y luego:

Result precedingOrMatchingResult = Session.Query<Result>().
    Where(r => r.TimeStamp < timeStamp).
    OrderByDescending(r => r.TimeStamp).
    FirstOrDefault();
 11
Author: Diego Mijelshon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-29 22:19:43

Ahora he descubierto que podría usar el método de extensión Take () en la instancia IQueryOver, y solo el enumerar a una lista, así:

Result precedingOrMatchingResult = Session.QueryOver<Result>().
        Where(r => r.TimeStamp < timeStamp).
        OrderBy(r => r.TimeStamp).Desc.   
        Take(1).List(). //enumerate only on element of the sequence!
        FirstOrDefault(); //get the preceding or matching result, if there is any
 35
Author: Marcel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-29 14:04:07
Result precedingOrMatchingResult = Session.QueryOver<Result>()
                                          .Where(r => r.TimeStamp < timeStamp)
                                          .OrderBy(r => r.TimeStamp).Desc
                                          .SingleOrDefault();
 22
Author: RRR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-10 03:35:45

Intenta

Result precedingOrMatchingResult = Session.QueryOver<Result>().
        Where(r => r.TimeStamp < timeStamp).
        OrderBy(r => r.TimeStamp).Desc.
        SetFetchSize(1).
        UniqueResult();

UniqueResult devolverá un solo valor, o null si no se encuentra ningún valor, que es un poco lo que hace First o Default.

Establecer el tamaño de búsqueda a 1 puede o no ser necesario, lo probaría con un generador de perfiles.

 10
Author: tom.dietrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-29 13:44:09