使用NHibernate根据子实体的活动选择实体

时间:2010-04-19 19:33:40

标签: c# sql nhibernate

我有一个星期一的案例......

我需要根据帖子评论集合中的近期活动选择博客帖子(帖子有List<Comment>属性,同样,评论有Post属性,建立关系。我不想显示相同的帖子两次,我只需要实体的一个子集,而不是所有的帖子。

首先想到的是抓住所有有评论的帖子,然后根据最新的评论订购。为了实现这一点,我很确定我必须将每个帖子的评论限制为第一个/最新评论。最后我只是选择前5位(或者我想传递给方法的最大结果数)。

第二个想法是抓住所有评论,按CreatedOn排序,并过滤所以每个帖子只有一个评论。然后返回那些顶级(无论如何)帖子。这看起来和第一个选项一样,只是穿过后门。

我有一个丑陋的,两个查询选项我已经使用了一些LINQ来进行过滤,但我知道在使用NHibernate API时有更优雅的方法。希望在这里看到一些好主意。

编辑:到目前为止,这对我有用。虽然它有效,但我确信有更好的方法可以做到......

// get all comments ordered by CreatedOn date
var comments = Session.CreateCriteria(typeof(Comment)).AddOrder(new Order("CreatedOn", false)).List<Comment>();
var postIDs = (from c in comments select c.ParentPost.ID).Distinct();

// filter the comments
List<Post> posts = new List<Post>();
foreach(var postID in postIDs)
{
    var post = Get(postID); // get a Post by ID
    if(!posts.Contains(post)) // this "if" is redundant due to the Distinct filter on the PostIDs collection
    {
        posts.Add(post);
    }
}

return posts;

1 个答案:

答案 0 :(得分:2)

这是使用NHibernate.LambdaExtensions语法,但应该很容易转换为标准条件查询或hql查询。

var query1 = DetachedCriteria.For<Post>()
    .CreateCriteria<Post>(x => x.Comments)
    .Add<Comment>(x => x.CreatedDate >= DateTime.Now.AddDays(-5));

query1.GetExecutableCriteria(session).List<T>();

您也可能希望热切地加载集合,并将此限制设置为适用于您希望避免拉回整个数据库的内容以及迭代加载延迟列表的N + 1查询条件。

使用NHibernate解决任何类型的复杂查询的第一步是从原始SQL开始,所以我们真的需要从像

这样的东西开始
Select P.*
From Post P
Where P.PostID Exists (
    Select P1.PostID
    From Posts P1 Inner Join Comments C ON ( P1.PostID = C.PostID )
    Where P1.PostID Exists (
        Select Top 5 C1.PostID, Count(*) as PostCount 
        From Comments C1
        Group By C1.PostID
        Order By PostCount DESC
    )
    And C.CreateDate > Now - 5 days
)

这是手工编写的,因此这更像是查询的近似值,应该能够指出您能够解决查询的方向。通过对此的一些反馈,我可以添加更多关于将其转换为NH的信息。最后的外部存在也可以在最终的NH版本中被删除,因为我相信Post with Comments的矩阵是NH将如何急切地加载实体。