NHibernate - Как написать этот запрос: выберите родителей и найдите ребенка для каждого родителя, соответствующего условию - PullRequest
1 голос
/ 15 сентября 2010

Хорошо, сначала моя простая модель предметной области - это 2 класса с отношением один-ко-многим, простое отношение Родитель -> ребенок. «Твит» имеет один или несколько «Голосов», но каждый Голос принадлежит только одному Твиту и т. Д.

public class Tweet
{
    public virtual long Id { get; set; }
    public virtual string Username { get; set; }
    public virtual string Message { get; set; }

    public virtual ISet<Vote> Votes { get; set; }
}

public class Vote
{
    public virtual long Id { get; set; }
    public virtual long TwitterUserId { get; set; }
    public virtual DateTime VotedDate { get; set; }

    public virtual Tweet Tweet { get; set; }
}

Я пытаюсь написать запрос в HQL, ICriteria или NHibernate LINQ, который выбирает все твиты, но также добавляет два столбца, которые выбирают:

  • Подсчет количества голосов, и ...
  • Голосовал ли конкретный пользователь за этот твит, основываясь на определенном TwitterUserId

С двумя дополнительными столбцами я не ожидаю возврата объекта домена Tweet, и, вероятно, потребуется выполнить запрос отчета, это нормально. Но я изо всех сил пытаюсь понять, как написать этот запрос.

Я знаю, как написать это как хранимую процедуру или используя LINQ 2 SQL. Если это поможет, я выражу это как запрос LINQ to SQL.

long userId = 123;

var tweets = from t in dataContext.Tweets
             where t.Application == app
             orderby t.PostedDate desc
             select new TweetReport()
             {
                 Id = t.Id,
                 Username = t.Username,
                 Message = t.Message,
                 TotalVotes = t.Votes.Count(),
                 HasVoted = t.Votes.Any(v => v.TwitterUserId == userId)
             };

Я знаю, что это будет работать в LINQ 2 SQL и генерировать достаточно эффективный T-SQL, но я не могу понять, как написать это в NHibernate.


Обновление: Я попытался выполнить указанный выше запрос LINQ в NHibernate с помощью поставщика NHibernate LINQ, созданного для NHibernate v2 , например:

var tweets = from t in Session.Linq<Tweet>()
             where (snip)

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


Обновление 2: Благодаря предложению Диего Миджелсона я обновился до NHibernate 3.0 alpha 2 и написал запрос в LINQ:

var tweets = from t in Session.Query<Tweet>()
             where t.App == app
             orderby t.PostedDate descending
             select t;

int totalRecords = tweets.Count();

var pagedTweets = (from t in tweets
                   select new TweetReport()
                   {
                       Id = t.Id,
                       TwitterId = t.TweetId,
                       Username = t.Username,
                       ProfileImageUrl = t.ImageUrl,
                       Message = t.Message,
                       DatePosted = t.PostedDate,
                       DeviceName = t.Device.Name,
                       DeviceUrl = t.Device.Url,
                       TotalVotes = t.Votes.Count(),
                       HasVoted = t.Votes.Any(v => v.TwitterUserId == userId)
                   })
                   .Skip(startIndex)
                   .Take(recordsPerPage)
                   .ToList();

return new PagedList<TweetReport>(pagedTweets,
    recordsPerPage, pageNumber, totalRecords);

1 Ответ

2 голосов
/ 15 сентября 2010

Точно так же с NHibernate 3; просто замените dataContext.Tweets на session.Query<Tweet>.

Кроме того, вы можете создать класс контекста, который представляет session.Query<Tweet> как свойство IQueryable<Tweet> Tweets, тогда код будет на 100% неизменным.

...