我有一个像这样的实体模型:
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; }
}
我正在尝试创建一个查询,它将为我提供所有请求,其最新的响应(关于其时间戳) )成功。怎么办呢?
答案 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
)
注意:
RequestId
//
注释而不是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)
;
此时我们必须嵌套内部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);
不知道这是否有效。