Consulta en referencia HasMany

Tengo un modelo de entidad como este:

public class Request { public virtual IList Responses { get; set; } } public class Response { public virtual DateTime Timestamp { get; set; } public virtual bool Success { get; set; } } 

Estoy tratando de crear una consulta que me dará todas las solicitudes donde su última respuesta (con respecto a su marca de tiempo ) es correcta . ¿Cómo puede hacerse esto?

Como casi siempre, NHibernate tiene una respuesta para esto. Lo que estamos tratando de lograr aquí sería una Declaración SQL que se parezca a esto:

 // final Request selection SELECT request.[RequestId] FROM [Request] request // Only requests, which are successful, and have Max(date) WHERE request.[RequestId] IN ( SELECT successResponse.RequestId as y0_ FROM [Response] successResponse // response which max date is equal to the upper response // and which RequestId corresponds with supper upper Request WHERE EXISTS ( SELECT maxResponse.RequestId as y0_ , max(maxResponse.[DateTime]) as y1_ FROM [Response] maxResponse // do the MAX only for current Request WHERE maxResponse.RequestId = successResponse.RequestId GROUP BY maxResponse.RequestId // assure that the Response match is on the max DateTime HAVING max(maxResponse.[DateTime]) = successResponse.[DateTime] ) AND successResponse.[Success] = 1 ) 

Notas:

  1. Esperando la respuesta tiene RequestId
  2. arriba se usó C # // comentario en lugar de SQL --

Y ahora la magia de NHibernate y QueryOver:

 // This declaration will allow us, to use a reference from middle SELECT // in the most deeper SELECT Response response = null; // the most INNER SELECT var maxSubquery = QueryOver.Of() .SelectList(l => l .SelectGroup(item => item.RequestId) .SelectMax(item => item.DateTime) ) // WHERE Clause .Where(item => item.RequestId == response.RequestId) // HAVING Clause .Where(Restrictions.EqProperty( Projections.Max(item => item.DateTime), Projections.Property(() => response.DateTime) )); // the middle SELECT var successSubquery = QueryOver.Of(() => response) // to filter the Request .Select(res => res.RequestId) .WithSubquery .WhereExists(maxSubquery) // now only these wich are successful .Where(success => success.Success == true) ; 

En este momento, tenemos SUB SELECT internos, nesteds. vamos a usarlos:

 // the most outer SELECT var query = session.QueryOver(); query.WithSubquery // our Request ID is IN(... .WhereProperty(r => r.ID) .In(successSubquery); var list = query .List(); 

Notas finales, no estoy discutiendo el concepto. No el rendimiento. Usaría más bien un ajuste en la respuesta “IsActive” y lo haría más fácil … esta es solo la respuesta de cómo hacerlo …

Voy a echar un vistazo a esto, aquí hay algo de linq (usando Query lugar).

 session.Query() .Where(request => request.Responses.Count() > 0 && request.Responses.OrderByDescending(response => response.Timestamp) .First() .Success); 

No tengo idea si esto funciona.