Использование NHibernate для выбора сущностей на основе активности дочерних сущностей - PullRequest
1 голос
/ 19 апреля 2010

У меня случай понедельника ...

Мне нужно выбрать сообщения в блоге на основе недавней активности в коллекции комментариев к сообщению (у сообщения есть свойство List<Comment>, а также у комментария есть свойство сообщения, устанавливающее связь. Я не хочу показывать то же самое опубликовать дважды, и мне нужно только подмножество объектов, а не все сообщения.

Сначала нужно было захватить все посты с комментариями, а затем упорядочить их по последним комментариям. Чтобы это работало, я уверен, что мне придется ограничить комментарии для каждого поста первым / новым комментарием. В заключение я бы просто взял первые 5 (или любое максимальное число результатов, которое я хочу передать в метод).

Во-вторых, нужно собрать все комментарии, упорядоченные по CreatedOn, и отфильтровать их, чтобы в каждом сообщении был только один комментарий. Затем верните эти лучшие (все) сообщения. Это похоже на первый вариант, просто пройти через заднюю дверь.

У меня ужасный вариант с двумя запросами. Я работал с некоторым LINQ на стороне для фильтрации, но я знаю, что есть более элегантный способ сделать это с помощью API NHibernate. Надеюсь увидеть здесь несколько хороших идей.

РЕДАКТИРОВАТЬ: Вот что работает для меня до сих пор. Хотя это работает, я уверен, что есть лучший способ сделать это ...

// 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 Ответ

2 голосов
/ 20 апреля 2010

Используется синтаксис 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, потому что я считаю, что матрица публикации с комментариями - это то, как NH будет охотно загружать сущности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...