外部右连接在NHibernate中不起作用

时间:2015-06-01 13:35:50

标签: mysql nhibernate orm fluent-nhibernate hql

所以我有两张桌子:

表1:

Item
id : int
title : varchar
comments : varchar

表2:

Rating
id : int
isUpvote : bit
date : datetime
item_id : int

一个项目可以有多个评级。 IsUpvote说明评级是喜欢还是不喜欢。

我正在使用NHibernate将ORM用于我的MySQL数据库。

想要制作一种趋势列表,以显示过去一段时间内最喜欢的项目(从dateTime X到现在)。

MySQL代码如下所示:

select p.id, sum(case when r.isUpvote = b'1' then 1 else 0 END) - sum(case when r.isUpvote=b'0' then 1 else 0 END) as score
from rating as r
right join item as p
on p.id = r.item_id
group by p.id
order by score desc
limit 7;

这导致:

  

Id - 得分

     

1 - 2

     

2 - 1

     

3 - 0

     

4 - 0

     

5 - 0

     

6 - 0

     

7 - 0

所以我想在NHibernate中这样做。我试过但是HQL和QueryOver,但我无法理解。我试过的是:

GetTrendingItems(int nrOfTrendingItems, DateTime fromDate) {
var trendingItems = Session
            .CreateQuery(@"select p, sum(case when r.IsUpvote = 1 then 1 else 0 END) - sum(case when r.IsUpvote=0 then 1 else 0 END) as score
                from Item as p, Rating as r
                where p.Id = r.Point.Id
                group by p.Id
                order by sum(case when r.IsUpvote = 1 then 1 else 0 END) - sum(case when r.IsUpvote=0 then 1 else 0 END) desc")
            .SetMaxResults(nrOfClimbers)
            .List();
}

我试过了:

GetTrendingItems(int nrOfTrendingItems, DateTime fromDate) {
DBRating dbRatingAlias = null;
        var iets = Session.QueryOver<DBRating>(() => dbRatingAlias)
            .Where(r => r.Date > fromDate)
            .OrderBy(Projections.Conditional(
                Restrictions.Where(() => dbRatingAlias.IsUpvote),
                Projections.Constant(1),
                Projections.Constant(-1))).Desc
            .Right.JoinQueryOver<DBPoints>(r => r.Point)
            .Take(nrOfClimbers)
            .List();
}

我在这里失去了希望。有人能帮助我吗?

更新: HQL生成此SQL:

 select
    dbpoints0_.id as col_0_0_,
    sum(case 
        when dbrating1_.isUpvote=1 then 1 
        else 0 
    end)-sum(case 
        when dbrating1_.isUpvote=0 then 1 
        else 0 
    end) as col_1_0_,
    dbpoints0_.id as id3_,
    dbpoints0_.active as active3_,
    dbpoints0_.title as title3_,
    dbpoints0_.comments as comments3_,
    dbpoints0_.score as score3_ 
from
    points dbpoints0_,
    Rating dbrating1_ 
where
    dbpoints0_.id=dbrating1_.points_id 
group by
    dbpoints0_.id 
order by
    sum(case 
        when dbrating1_.isUpvote=1 then 1 
        else 0 
    end)-sum(case 
        when dbrating1_.isUpvote=0 then 1 
        else 0 
    end) desc limit ?p0;
?p0 = 10 [Type: Int32 (0)]

并且Fluent生成此SQL:

SELECT
    this_.id as id6_0_,
    this_.owners_id as owners2_6_0_,
    this_.points_id as points3_6_0_,
    this_.isUpvote as isUpvote6_0_,
    this_.date as date6_0_ 
FROM
    Rating this_ 
WHERE
    this_.date > ?p0 
ORDER BY
    (case 
        when this_.isUpvote = ?p1 then ?p2 
        else ?p3 
    end) desc limit ?p4;
?p0 = 25-5-2015 22:39:49 [Type: DateTime (0)],
?p1 = True [Type: Boolean (0)],
?p2 = 1 [Type: Int32 (0)],
?p3 = -1 [Type: Int32 (0)],
?p4 = 10 [Type: Int32 (0)]

1 个答案:

答案 0 :(得分:0)

我在de MySQL数据库中创建了一个存储过程

DELIMITER //
create procedure getTrending
    (IN $getClimbers bool,
    IN $fromDate DateTime,
    IN $nrOfTrending int)
Begin
    if ($getClimbers) then
        select p.id, p.active, p.title, p.comments, 
        sum(case when r.isUpvote = b'1' and r.date > $fromDate then 1 else 0 END) - sum(case when r.isUpvote=b'0' and r.date > $fromDate  then 1 else 0 END) as score
        from rating as r
        right join points as p
        on p.id = r.points_id
        group by p.id
        order by sum(case when r.isUpvote = b'1' and r.date > $fromDate then 1 else 0 END) - sum(case when r.isUpvote=b'0' and r.date > $fromDate  then 1 else 0 END) desc
        limit $nrOfTrending;
    else
        select p.id, p.active, p.title, p.comments,
        sum(case when r.isUpvote = b'1' and r.date > $fromDate then 1 else 0 END) - sum(case when r.isUpvote=b'0' and r.date > $fromDate  then 1 else 0 END) as score
        from rating as r
        right join points as p
        on p.id = r.points_id
        group by p.id
        order by sum(case when r.isUpvote = b'1' and r.date > $fromDate then 1 else 0 END) - sum(case when r.isUpvote=b'0' and r.date > $fromDate  then 1 else 0 END) asc
        limit $nrOfTrending;
    end if;
end //
DELIMITER ;

然后从我的C#代码调用它:

public virtual List<DBPoints> GetClimbers(int nrOfClimbers, DateTime fromDate)
        {
            OpenSession();
            var query = Session.GetNamedQuery("getTrending");
            query.SetBoolean("getClimbers", true);
            query.SetDateTime("fromDate", fromDate);
            query.SetInt32("nrOfTrending", nrOfClimbers);
            var pointList = query.List<DBPoints>();
            CloseSession();
            return pointList.ToList();
        }

对于Nhibernate,需要制作这样的映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="TechDash.Business"
                   namespace="TechDash.Business.Models.Database">

  <sql-query name="getTrending">
<return class="DBPoints" />
call getTrending(:getClimbers, :fromDate, :nrOfTrending)

由于我返回的列的名称与我在检索Points对象时返回的列名相同,因此我不必创建新的C#对象,也不必使用映射属性那个C# - 对象。