Search code examples
sqlfluent-nhibernatesubqueryicriterianhibernate-criteria

Nhibernate Criterias inner join subquery


Im trying to replicate the following sql in Nhibernate ICriteria

    SELECT DISTINCT AP.ID
FROM ActivityParts AP
    INNER JOIN ActivityBookings AB ON AB.ActivityPartID = AP.ID
    INNER JOIN OrderPartBookings OPB ON OPB.ActivityBookingID = AB.ID
    INNER JOIN OrderParts OP ON OP.ID = OPB.OrderPartID
    INNER JOIN Orders O ON O.ID = OP.OrderID
    LEFT JOIN Invoices I ON I.ID = (SELECT TOP 1 ID FROM Invoices WHERE OrderReferenceID = OP.ID AND Cancelled = 0 ORDER BY Created DESC)
WHERE
    O.OrderStatus != 'Cancelled'
    AND OP.Payed = 0
    AND (I.ID IS NOT NULL AND DATEADD(Day,1, I.DueDate) < @date)

So far i have managed to get the following (Note: I havent profiled it so im not quite sure how similar the sql becomes through the criteria):

var invoiceSubCrit = DetachedCriteria.For<Invoice>()
            .Add(Restrictions.Eq("Cancelled", false))
            .Add(Restrictions.EqProperty("OrderReference", "OP.ID"))
            .AddOrder(NhOrder.Desc("Created"))
            .SetProjection(Projections.Property("DueDate"))
            .SetMaxResults(1);

        var crit = Session.CreateCriteria<OrderPart>("OP")
            .CreateCriteria("OP.Bookings", "AB", JoinType.InnerJoin)
            .CreateCriteria("OP.Order", "O", JoinType.InnerJoin)
            .CreateCriteria("AB.ActivityPart", "AP", JoinType.InnerJoin)
            .Add(NhExpression.Eq("AP.ID", ActivityID))
            .Add(NhExpression.Eq("OP.Payed", false))
            .Add(NhExpression.Not(NhExpression.Eq("O.OrderStatus", OrderStatus.Cancelled)))
            .Add(NhExpression.Not(NhExpression.Eq("AB.Status", QueueStatus.Reserve)))
            .Add(Subqueries.Lt(DateTime.Now.Date.AddDays(1), invoiceSubCrit))
            .SetResultTransformer(new DistinctRootEntityResultTransformer());

Uppdate: Got some new info and have refactored the sql a bit. Uppdate: Got a semi working subquery, need to figure out how to set it upp correctly.


Solution

  • Finally got it working and have updated my criteria code with the final working version in my case. I don't know exactly how close this is to my original SQL code but the result seams to be the same wich is the most important.

    var invoiceSubCrit = DetachedCriteria.For<Invoice>()
                .Add(Restrictions.Eq("Cancelled", false))
                .Add(Restrictions.EqProperty("OrderReference.ID", "OP.ID"))
                .AddOrder(NhOrder.Desc("Created"))
                .SetProjection(Projections.Property("DueDate"))
                .SetMaxResults(1);
    
            var crit = Session.CreateCriteria<OrderPart>("OP")
                .CreateCriteria("OP.Bookings", "AB", JoinType.InnerJoin)
                .CreateCriteria("OP.Order", "O", JoinType.InnerJoin)
                .CreateCriteria("AB.ActivityPart", "AP", JoinType.InnerJoin)
                .Add(NhExpression.Eq("AP.ID", ActivityID))
                .Add(NhExpression.Eq("OP.Payed", false))
                .Add(NhExpression.Not(NhExpression.Eq("O.OrderStatus", OrderStatus.Cancelled)))
                .Add(NhExpression.Not(NhExpression.Eq("AB.Status", QueueStatus.Reserve)))
                .Add(Subqueries.Gt(DateTime.Now.Date, invoiceSubCrit))
                .SetResultTransformer(new DistinctRootEntityResultTransformer());