NHibernate QueryOver GroupBy

时间:2016-10-13 08:34:25

标签: nhibernate fluent-nhibernate queryover

我们如何在QueryOver中干净地进行分组?我上周要求使用下面的示例解决它,但我必须检查nhibernate发送给SQL的结束查询并从那里找到别名。

subQuery.Select(
  Projections.ProjectionList().Add(
    Projections.SqlGroupProjection(
      "this_0_.Id as idAlias", 
      $"this_0_.Id, this_0_.StartDate, this_0_.DateCreated, this_0_.PricePerAdult, 
          this_0_.EmptySeats, reservatio5_.NumberOfParticipants", 
    new string[] { "idAlias" }, new IType[] { Hibernate.NHibernateUtil.Int32 }))
);

如您所见,分组变量可以在子查询或主查询上完成。我们需要一种方法将reservationAlias.NumberOfParticipants转换为字符串至少。

编辑:添加完整代码

Agent agentAlias = null;
AgentProduct agentProductAlias = null;
Operator operatorAlias = null;
Product productAlias = null;
Session sessionAlias = null;
Slot slotAlias = null;
Reservation reservationAlias = null;
UserReservation userReservationAlias = null;
GroupDiscount groupDiscountAlias = null;

var subQuery = QueryOver.Of<Slot>(() => slotAlias)
    .JoinAlias(() => slotAlias.Session, () => sessionAlias)
    .JoinAlias(() => sessionAlias.Product, () => productAlias)
    .JoinAlias(() => productAlias.Operator, () => operatorAlias)
    .Left.JoinAlias(() => sessionAlias.GroupDiscounts, () => groupDiscountAlias)
    .Left.JoinAlias(() => slotAlias.Reservation, () => reservationAlias)
    .Left.JoinAlias(() => reservationAlias.UserReservations, () => userReservationAlias, () => userReservationAlias.Status != UserReservationStatus.Expired);

if (agentGuid.HasValue)
{
    subQuery.JoinAlias(() => productAlias.AgentProducts, () => agentProductAlias)
        .JoinAlias(() => agentProductAlias.Agent, () => agentAlias)
        .Where(() => agentAlias.Guid == agentGuid.Value);
}
if (operatorGuid.HasValue)
{
    subQuery = subQuery.Where(() => operatorAlias.Guid == operatorGuid.Value);
}

if (productGuid.HasValue)
{
    subQuery = subQuery.Where(() => productAlias.Guid == productGuid.Value);
}

if (minimumDiscount.HasValue)
{
    subQuery.Where(() => groupDiscountAlias.DiscountPercentage >= minimumDiscount.Value);
}

if (bookingQuery.HasValue)
{
    if (bookingQuery.Value)
    {
        subQuery.Where(() => userReservationAlias.Id != null);
    }
    else
    {
        subQuery.Where(() => userReservationAlias.Id == null);
    }
}

if (from.HasValue)
{
    subQuery = subQuery.Where(() => slotAlias.StartDate >= from);
}

if (to.HasValue)
{
    subQuery = subQuery.Where(() => slotAlias.StartDate <= to);
}

if (onlyAvailable)
{
    //Show slots that's not in cutoff. StartDate > Now + Cutoff
    subQuery = subQuery.Where(Restrictions.GtProperty(
        Projections.Property(() => slotAlias.StartDate),
        Projections.SqlFunction(
            "addminutes",
            NHibernateUtil.DateTimeOffset,
            Projections.Conditional(
                Restrictions.Eq(Projections.Property(() => reservationAlias.LastMinuteCutoff), true),
                Projections.Constant(0),
                Projections.Property(() => productAlias.CutoffOffset)
            ),
            Projections.Constant(DateTimeOffset.UtcNow))));

    subQuery.Where(() => reservationAlias.Id == null || reservationAlias.OperatorStatus != ReservationStatus.Rejected);

    if (onlyGroupSlots)
    {
        subQuery.Where(() => userReservationAlias.Id == null);
    }
    else if (onlyDeals)
    {
        subQuery.Where(() => userReservationAlias.Id != null);
    }
    else
    {
        subQuery =
            subQuery.Where(
                () => reservationAlias.Id == null ||
                    reservationAlias.OperatorStatus == ReservationStatus.Accepted ||
                    reservationAlias.OperatorStatus == ReservationStatus.Pending);
    }
}
var pageSubQuery = subQuery.Clone()
    .Select(
        Projections.ProjectionList().Add(
            Projections.SqlGroupProjection("this_0_.Id as idAlias", 
            $"this_0_.Id, this_0_.StartDate, this_0_.DateCreated, this_0_.PricePerAdult, this_0_.EmptySeats, reservatio5_.NumberOfParticipants", 
            new string[] { "idAlias" }, new IType[] { NHibernate.NHibernateUtil.Int32 })));

pageSubQuery = SortSlotsQuery(pageSubQuery, () => reservationAlias, sortBy) as QueryOver<Slot, Slot>;

pageSubQuery.Skip(offset).Take(limit);

var queryOver = session.QueryOver(() => slotAlias)
    .JoinAlias(() => slotAlias.Session, () => sessionAlias)
    .JoinAlias(() => sessionAlias.Product, () => productAlias)
    .JoinAlias(() => productAlias.Operator, () => operatorAlias)
    .Left.JoinAlias(() => slotAlias.Reservation, () => reservationAlias)
    .Left.JoinAlias(() => sessionAlias.GroupDiscounts, () => groupDiscountAlias);

queryOver = SortSlotsQuery(queryOver, () => reservationAlias, sortBy);

var result = queryOver.WithSubquery.WhereProperty(x => x.Id).In(pageSubQuery)
    .TransformUsing(Transformers.DistinctRootEntity)
    .Future();

var rowCount = subQuery.GetExecutableQueryOver(session).Select(Projections.CountDistinct<Slot>(x => x.Id)).FutureValue<int>();

return new PagenedResult<Slot>(rowCount.Value, offset, limit, result.ToArray());

代码的作用:获取插槽,过滤它们,然后创建分页子查询。然后使用分页子查询中的必要联接从数据库中提取插槽。这样我就可以通过一次数据库访问。

0 个答案:

没有答案