Эффективное извлечение объекта с помощью вложенных коллекций с использованием NHibernate - PullRequest
2 голосов
/ 09 ноября 2010

Я создаю приложение для опроса, в котором у меня есть опрос, в котором есть коллекция страниц.На каждой странице будет набор вопросов, и каждый вопрос будет иметь набор вариантов ответов.Моя структура классов выглядит следующим образом:

public class Survey : Entity {
    public IList<Page> Pages { get; set; }
}

public class Page : Entity {
    public IList<Question> Questions { get;set; }
}

public class Question : Entity {
    public IList<Option> Options { get; set; }
}

public class Option : Entity {}

Отображение для каждого класса:

<!-- mapping for ID and other properties excluded -->
<class name="Survey">
    <bag name="Pages" generic="true" inverse="true">
        <key column="SurveyId" />
        <one-to-many class="Page" />
    </bag>
    <bag name="Questions" access="none">
        <key column="SurveyId" />
        <one-to-many class="Question" />
    </bag>
</class>

<class name="Page">
    <many-to-one name="Survey" column="SurveyId" />
    <bag name="Questions" generic="true" inverse="true">
        <key column="PageId" />
        <one-to-many class="Question" />
    </bag>
</class>

<class name="Question">
    <many-to-one name="Page" column="PageId" />
    <many-to-one name="Survey" column="SurveyId" />
    <bag name="Options" generic="true" inverse="true">
        <key column="QuestionId" />
        <one-to-many class="Option" />
    </bag>
</class>

<class name="AnswerOption">
    <many-to-one name="Question" column="QuestionId" />
</class>

Мне нужно отобразить все вопросы на странице, поэтому я начну с объекта опроса и циклачерез страницы, предметы и опции.Это заставляет NHibernate выполнять много запросов, и я хотел бы оптимизировать это.Как получить объект опроса с вложенными коллекциями наилучшим образом, не выполняя слишком много запросов?

Это код, который у меня есть в данный момент, но он все еще выполняет много запросов:

var result = Session.CreateMultiQuery()
    .Add(Session.CreateQuery("from Survey s inner join fetch s.Pages where s.Id = :id"))
    .Add(Session.CreateQuery("from Survey s inner join fetch s.Question where s.Id = :id"))
    .SetInt32("id", id)
    .List();

IList list = (IList)result[0];
return list[0] as Survey;

Я также пробовал запросы на будущее, но они не помогают сократить количество запросов.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 11 ноября 2010

Если я правильно понял, вы можете добиться этого с помощью следующего HQL (конечно, ту же идею можно использовать с ICriteria)

from Survey s
  inner join fetch s.Pages p
  inner join fetch p.Questions q
  inner join fetch q.Options
where s.Id = :id

Если вы также хотите получить survey.Questions, то лучшим вариантом будет выборка из них в отдельном qyery и использованных фьючерсах, чтобы избежать декартового произведения.

Кроме того, если я правильно помню, HQL-запросы игнорируют выборки, определенные в отображениях. Если коллекция отображается с помощью lazy="false" fetch="join", то она извлекается при использовании ICriteria, но не при использовании HQL.

1 голос
/ 09 ноября 2010

Вы можете попробовать добавить

lazy="false" fetch="join"

к вашей сумке объявлений. Таким образом, вы можете быть уверены, что пакет будет доставлен по одному запросу.

0 голосов
/ 10 ноября 2010

Решением, которое я использую, является обратная связь между сущностями.Благодаря этому вы можете быть уверены, что при загрузке записи Survey запись Page не загружается, если вы не вызовете метод LoadAll.LoadAll - это метод в каждом классе, который ищет все связанные записи.Рассмотрим следующий код:

public class Survey : Entity {
Survey[] LoadAll {
string hql = "from Page page where page.SurveyID =" + this.ID;
//....
}
}

public class Page : Entity {
    public Survey { get;set; }
}

public class Question : Entity {
    public Page Page { get; set; }
}

public class Option : Entity {
    public Question Question {set; get;}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...