Я использую будущие запросы NHibernate в веб-приложении MVC 3 и пытаюсь сохранить весь доступ к моей базе данных в моих контроллерах, а не в моих представлениях. каталог ресурсов (описательные аннотации), которые содержат коллекцию оценок "многие ко многим" и коллекцию тем "многие ко многим". Пользователи выбирают одну или несколько оценок и одну или несколько тем, а затем получают список подходящих ресурсов.
Чтобы заполнить форму поиска, я использую будущие запросы для получения всех оценок и тем:
public Domain.SearchFormData GetSearchFormData()
{
// Get all grades and all topics using a multiquery.
IEnumerable<Grade> grades = Session.QueryOver<Grade>()
.Future();
IEnumerable<Topic> topics = Session.QueryOver<Topic>()
.Future();
var result = new SearchFormData();
result.Grades = grades;
result.Topics = topics;
return result;
}
Это очень просто, отлично работает и возвращает SearchFormData
, который является простым DTO. Этот запрос выполняется в контроллере, и результат не требует дальнейшей обработки, поэтому он передается прямо в представление для визуализации в виде списков флажков.
Но из-за ленивого выполнения при будущих запросах доступ к базе данных не запускается, пока представление не начнет итерацию списков. Это считается некоторыми ( как NHibernate Profiler), и они говорят, что к тому времени, когда представление начнет рендеринг, весь доступ к базе данных должен быть выполнен. Основная причина в том, что в противном случае легко иметь скрытый SELECT N + 1.
Здесь это не применимо; и оценка, и тема - простые объекты без коллекций. Я не особо возражаю, что представление вызовет доступ к базе данных. Но это заставляет меня искать чистый, ясный способ инициировать все будущие запросы. Один из способов сделать это - получить доступ к результатам, например скопировав IEnumerable
в список. Но это не совсем то, что мне нужно делать; Я просто хочу выполнить поставленные в очередь запросы.
Я думаю, что триггер имеет смысл срабатывать вне указанного выше запроса. Мне могут понадобиться другие данные для рендеринга полного просмотра страницы, и я могу использовать другие будущие запросы для их получения. Например, на домашней странице также могут отображаться пять самых популярных ресурсов и общее количество ресурсов. Тогда контроллер будет вызывать несколько методов для накопления того, что ему нужно для представления, и было бы наиболее эффективно выполнять их все сразу. Конечно, один из способов сделать это - расширить мои GetSearchFormData
до GetAllHomePageData
и вернуть DTO с полями для всего на домашней странице. Но я использую форму поиска повсюду, а не только на домашней странице. Таким образом, я бы потерял некоторую красивую модульность.