查询HasMany引用

dhr*_*hrm 5 c# nhibernate

我有一个像这样的实体模型:

public class Request
{
    public virtual IList<Response> Responses { get; set; }
}

public class Response
{
    public virtual DateTime Timestamp { get; set; }
    public virtual bool Success { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个查询,它将向我提供所有请求,其中最新的响应(关于其时间戳)是成功的.如何才能做到这一点?

Rad*_*ler 7

由于几乎总是,NHibernate的确实有这个答案.我们在这里尝试实现的将是一个SQL语句,如下所示:

// 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
   )
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 期待响应 确实有 RequestId
  2. 上面使用的是C#//comment而不是SQL--

而现在NHibernate和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<Response>()
   .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<Response>(item => item.DateTime),
      Projections.Property(() => response.DateTime)
    ));

// the middle SELECT
var successSubquery = QueryOver.Of<Response>(() => response)
    // to filter the Request
    .Select(res => res.RequestId)
    .WithSubquery
    .WhereExists(maxSubquery)
    // now only these wich are successful
    .Where(success => success.Success == true)
    ;
Run Code Online (Sandbox Code Playgroud)

此时我们必须嵌套内部SUB SELECT.让我们用它们:

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

var list = query
    .List<Request>();
Run Code Online (Sandbox Code Playgroud)

最后的笔记,我不是在讨论这个概念.不是表现.我会在响应"IsActive"上使用相当的设置并使其更容易 ......这只是答案如何做到这一点......