NHibernate: шаблон для возврата полностью загруженных экземпляров из репозиториев - PullRequest
0 голосов
/ 19 июля 2010

Как часть моего бесконечного чистилища DAL, вдохновленного NHibernate, я начал использовать шаблон Repository, чтобы держать NHibernate на расстоянии вытянутой руки от моего слоя пользовательского интерфейса. Вот пример метода Load из репозитория.

public StoredWill Load(int id)
{
  StoredWill storedWill;
  using (ISession session = NHibernateSessionFactory.OpenSession())
  {
    storedWill = session.Load<StoredWill>(id);
  }
  return storedWill;
}

Мне нравится тот факт, что мой сайт не знает, что такое ISession.

Естественно, я начал получать ленивые исключения инициализации, потому что описанный выше метод не загружает StoredWill, он просто возвращает прокси. Когда вы получаете доступ к свойствам прокси-сервера, вы получаете исключение, потому что вы больше находитесь в рамках ISession. Я громко рассмеялся, когда понял, что происходит.

Я исправил это с помощью:

public StoredWill Load(int id)
{
  StoredWill storedWill;
  using (ISession session = NHibernateSessionFactory.OpenSession())
  {
    storedWill = session.Load<StoredWill>(id);
    string iReallyCouldntCareLess = storedWill.TestatorLastName;
  }
  return storedWill;
}

Но все это выглядит немного глупо . Кто-нибудь использует чуть более элегантный узор?

Люблю вас, ребята.

David

Ответы [ 4 ]

4 голосов
/ 20 июля 2010

Используйте внедрение зависимостей и передайте ISession своим классам репозитория через их конструкторы.Это единственный способ разрешить нескольким репозиториям участвовать в одной транзакции.

Ваш веб-сайт должен знать ISession, потому что именно там определены границы транзакций.Вы можете использовать шаблон сеанса для запроса, чтобы на ISession ссылались только в модуле HttpRequest или Global.asax.Или вы можете использовать платформу или использовать NHibernate и контролировать транзакции на страницах.

1 голос
/ 19 июля 2010
public StoredWill Load(int id)
{
  StoredWill storedWill;
  using (ISession session = NHibernateSessionFactory.OpenSession())
  {
    storedWill = session.Load<StoredWill>(id);
    // force an eager load within the session
    NHibernateUtil.Initialize(storedWill.TestatorLastName);
  }
  return storedWill;
}
1 голос
/ 19 июля 2010

Ознакомьтесь с ncommon framework ;у него есть хорошая реализация стратегий извлечения, которые идеально подходят для такого рода задач.Вы можете прочитать больше о том, как это реализовано, в блоге автора .

Я также должен отметить, что использование вашего сеанса немного отклонено ... вы действительно должны контролировать жизненный цикл своегосеанс выше (скажем, на уровне контроллера или httpmodule в зависимости от вашего интерфейса).Открытие нового сеанса для каждого действия с репозиторием является основным препятствием в мире nhibernate.

0 голосов
/ 21 февраля 2011

Часть вашей проблемы заключается в том, что вы используете Session.Load () вместо Session.Get () .

см. Эту статью Ayende Rahien - Разница между Get, Load и запросом по id для подробного описания двух.

Когда вы вызываете Session.Load () , вы указываете nhibernate создать прокси-объект идентификатора, который вы предоставляете. При этом nhibernate фактически не будет вызывать базу данных для извлечения данных. Это означает, что если вы Session.Load () с чем-то, чего нет в базе данных, оно выдаст исключение. Поскольку вы закрываете сеанс до доступа к объекту, вы не можете получить доступ к данным, поскольку сеанс прокси теперь закрыт.

Простым решением было бы изменить код для использования Session.Get () . Это загрузит ваш класс StoredWill из базы данных и заполнит ваш объект данными, которые ему нужны. Однако обратите внимание, что если у вас есть какие-либо внутренние классы или коллекции внутри вашего объекта, он просто создаст для них прокси. Если вам нужно получить все за один раз, вы можете использовать один из множества механизмов запросов для быстрой загрузки необходимых вам частей или использования проекций.

Надеюсь, в этом есть смысл:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...