Использование HQL NHibernate для создания запроса с несколькими внутренними объединениями - PullRequest
1 голос
/ 18 апреля 2010

Проблема здесь заключается в переводе оператора, написанного в синтаксисе LINQ to SQL, в эквивалент для NHibernate. Код LINQ to SQL выглядит так:

var whatevervar = from threads in context.THREADs
                          join threadposts in context.THREADPOSTs
                            on threads.thread_id equals threadposts.thread_id
                          join posts1 in context.POSTs
                            on threadposts.post_id equals posts1.post_id
                          join users in context.USERs
                            on posts1.user_id equals users.user_id
                          orderby posts1.post_time
                          where threads.thread_id == int.Parse(id)
                          select new
                          {
                              threads.thread_topic,
                              posts1.post_time,
                              users.user_display_name,
                              users.user_signature,
                              users.user_avatar,
                              posts1.post_body,
                              posts1.post_topic
                          };

По сути, это попытка получить список сообщений в данной ветке форума. Лучшее, что я смог придумать (с помощью полезных пользователей этого сайта) для NHibernate:

var whatevervar = session.CreateQuery("select t.Thread_topic, p.Post_time, " +
                                              "u.User_display_name, u.User_signature, " +
                                              "u.User_avatar, p.Post_body, p.Post_topic " +
                                              "from THREADPOST tp " +
                                              "inner join tp.Thread_ as t " +
                                              "inner join tp.Post_ as p " +
                                              "inner join p.User_ as u " +
                                              "where tp.Thread_ = :what")
                                              .SetParameter<THREAD>("what", threadid)
                                              .SetResultTransformer(Transformers.AliasToBean(typeof(MyDTO)))
                                              .List<MyDTO>();

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

public class MyDTO
{
    public string thread_topic { get; set; }
    public DateTime post_time { get; set; }
    public string user_display_name { get; set; }
    public string user_signature { get; set; }
    public string user_avatar { get; set; }
    public string post_topic { get; set; }
    public string post_body { get; set; }
}

У меня нет идей, и хотя это возможно сделать прямым SQL-запросом, я бы хотел сделать это правильно, без ущерба для цели использования ORM.

Заранее спасибо!

EDIT:

База данных выглядит следующим образом: http://i41.tinypic.com/5agciu.jpg (пока нельзя публиковать изображения.)

Ответы [ 2 ]

0 голосов
/ 18 апреля 2010

HQL - это запрос к вашим объектам, а не к вашим таблицам!

В вашем HQL я вижу соединение между классом tp и свойством этого класса, tp.Thread_. Там следует различать SQL и HQL. Думайте о HQL как о запросе к объекту TP, а не к базовой структуре таблицы. Можете ли вы опубликовать модель вашего домена (отношения между вашими объектами), чтобы мы могли вам помочь?

Спасибо за эту фотографию. Однако: похоже, что ваши объекты являются копией ваших таблиц, и я не думаю, что это то, что вы имели в виду? Например: я бы подумал, что отношение «многие ко многим» между темами и сообщениями будет отображаться с помощью Hibernate. Если бы это было так, вы могли бы объединять потоки с сообщениями, не беспокоясь о промежуточном объекте threadpost, который, фактически, просто поддерживает отношения между этими объектами, верно?

Другими словами; украсьте свой объект потока списком сообщений и украсьте объект сообщения списком потоков.

[украсьте] То есть поместить список потоков в качестве свойства в свой класс сообщений и поместить список сообщений в качестве свойства в свой класс потоков. То, что вы ищете, это отношение «многие ко многим» для файлов отображения nhibernate. Это означает, что вам не нужно отображать таблицу «многие ко многим» в классе, а только отображать отношения классов записей и потоков.

0 голосов
/ 18 апреля 2010

Когда я хочу, чтобы запрос HQL возвращал пользовательский тип, как вы, я всегда делаю это так:

select new MyDTO (t.Thread_Topic, p.Post_time, u.User_Display_Name, .... ) 
from ...

Мне бы пришлось проверить какой-то мой код, но я думаю, что в таких случаях я даже не использую AliasToBeenTransformer. Я не знаю наизусть, так как я в основном использую ICriteria API от NHibernate (и при его использовании вам действительно нужно указать преобразователь результатов при выполнении операций такого типа).

NB. Мне странно (или, скорее, неловко) видеть подчеркивания в именах свойств ...

...