Где поставить логику запроса NHibernate? - PullRequest
4 голосов
/ 11 мая 2010

Я пытаюсь настроить правильную архитектуру домена, используя Fluent NHibernate и Linq to NHibernate. У меня есть свои контроллеры, вызывающие мои классы репозитория, которые выполняют NHibernate и передают обратно ICollections данных. Кажется, это работает хорошо, потому что абстрагирует доступ к данным и сохраняет функциональность NHibernate в «мелком шрифте».

Однако сейчас я нахожу ситуации, когда моим контроллерам нужно использовать одни и те же вызовы данных в другом контексте. Например, мой репо возвращает список пользователей. Здорово, когда я хочу отобразить список пользователей, но когда я хочу начать использовать дочерние классы для показа ролей и т. Д., Я сталкиваюсь с проблемами SELECT N + 1. Я знаю, как это изменить в NHibernate, чтобы он вместо этого использовал соединения, но мой конкретный вопрос: ГДЕ я могу поместить эту логику? Я не хочу, чтобы каждый вызов GetAllUsers () также возвращал роли, но я хочу, чтобы некоторые из них.

Итак, вот мои три варианта, которые я вижу:

  1. Измените настройку в моем сопоставлении, чтобы роли присоединились к моему запросу.
  2. Создание двух вызовов репозитория - GetAllUsers () и GetUsersAndRoles ().
  3. Верните мой объект IQueryable из репозитория в контроллер и используйте метод NHibernate Expand.

Извините, если я не очень хорошо объяснил это. Я просто прыгаю в DDD, и эта терминология для меня все еще нова. Спасибо!

Ответы [ 4 ]

2 голосов
/ 11 мая 2010

Как указывает lomaxx, вам нужен query.Expand.

Чтобы предотвратить затенение хранилища всеми видами методов для каждой возможной ситуации, вы можете создать объекты запросов, которые выполняют настраиваемые запросы.

Я опубликовал несколько примеров с использованием API-интерфейса ICriteria в своем блоге . API ICriteria имеет FetchMode вместо Expand, но идея та же.

1 голос
/ 11 мая 2010

Я пытаюсь сохранить всю логику запросов в своих репозиториях и пытаюсь только передать обратно ICollection из них.

В вашей ситуации я бы передал некоторые параметры, чтобы определить, хотите ли вы загружать роли или нет, и создать IQueryable таким образом. Например:

GetAllUsers(bool loadRoles)
{
    var query = session.Linq<Users>();
    if(loadRoles)
       query.Expand("Roles");
    return query.ToList();
}
0 голосов
/ 11 мая 2010

Звучит так, будто вы спрашиваете, можно ли заставить GetAllUsers() иногда возвращать только сущности пользователей, а иногда возвращать пользователей и роли.

Я бы либо создал отдельный метод хранилища под названием GetRolesForUser(User user), использовал бы ленивую загрузку для ролей, либо использовал GetAllUsers(bool loadRoles), упомянутый в ответе lomaxx.

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

0 голосов
/ 11 мая 2010

Я бы выбрал 2, создав два репозитория. И, возможно, я бы рассмотрел создание еще одного вызова хранилища для GetRoleByUser (пользователь пользователя). Таким образом, вы можете получить доступ к роли пользователя при изменении выбора пользователя в отдельном потоке, если это необходимо, так что это повысит вашу производительность и не будет загружать роли каждого пользователя для каждого из ваших пользователей, что потребует большинства ресурсов.

...