查询HasMany引用

时间:2013-12-11 19:58:49

标签: 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; }
}

我正在尝试创建一个查询,它将为我提供所有请求,其最新的响应(关于其时间戳) 成功。怎么办呢?

2 个答案:

答案 0 :(得分: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
   )

注意:

  1. 期待响应 确实 RequestId
  2. 上面的
  3. 使用了C#//注释而不是SQL --
  4. 现在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)
        ;
    

    此时我们必须嵌套内部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>();
    

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

答案 1 :(得分:0)

我会抓住这个,这里有一些linq(改为使用Query)。

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

不知道这是否有效。