Метод единицы работы с отложенной загрузкой, nHibernate, ASP.NET MVC, Castle Windsor - PullRequest
3 голосов
/ 17 декабря 2010

Учитывая довольно простую структуру в C # ...

class Member
{
 virtual string Email { get; set; }
 virtual IList<Character> Characters { get; set; }
}

class Character
{
 virtual string Name { get; set; }
}

interface IMemberRepository
{
 MemberCreateStatus CreateMember(string email, string password);
 bool ValidateMember(string email, string password);
 Member RetrieveMember(string email);
 void SaveMember(Member member);
}

interface ICharacterRepository
{
 Character CreateCharacter(string name);
}


class MemberRepository : IMemberRepository
{
 private readonly ISessionFactory sessionFactory;

 public MemberRepository(ISessionFactory sessionFactory)
 {
    this.sessionFactory = sessionFactory;
 }

 // 
 public Member RetrieveMember(string email)
 {
    using(var session = sessionFactory.OpenSession())
    {
      return // member retrieval query
    }
 }
}

У меня есть приложение ASP.NET MVC, настроенное для использования nHibernate (свободная конфигурация) и Castle.Windsor для IoC. Это работает хорошо и хорошо, но в этом и заключается проблема.

Ленивая загрузка

По умолчанию, IList<Character> загружается лениво в большинстве любых ORM (nHibernate, Entity Framework и т. Д.) - теперь это неплохо, но я столкнулся с большим количеством путаницы в отношении того, как подойти к этому сценарию.

  • Я хочу добавить Character к Member. По логике вещей, я бы использовал Member.Characters.Add(n);, а затем позвонил бы MemberRepository.SaveMember(m);

В настоящее время эта проблема связана с концепцией Единица работы . Я должен создать Session, выполнить работу, а затем уничтожить ее после возвращения результатов. Это прекрасно работает, но теперь у меня есть следующий объект ...

Member

  • nHibernate Lazy Loaded Proxy (IList<Character>)
  • Email

Итак, я звоню var member = memberRepository.RetrieveMember(email); в моем Controller, затем я звоню member.Characters.Add(character); И вот тут начинается беспорядок.

Коллекция не существует, поскольку она загружена с отложенной загрузкой, а Session удален.

Итак, каков ответ? Конечно, я мог бы установить IList<Character>, чтобы не Lazy Load, но это просто глупо. Одна из крупнейших библиотек ORM в мире не использовала бы отложенную загрузку, если бы мешала базовой структуре проекта. Как эта концепция UnitOfWork играет на паттерне IRepository<T> IoC и зависимости впрыска?

Моей первой мыслью было просто абстрагировать задачу от репозитория и включить метод AddCharacter(Character character) в IMemberRepository, но теперь мне сказали, что «это не то, для чего предназначены репозитории». Так что я не совсем уверен, что делать с этого момента. Программно я знаю много решений, но мне нужно понять, что решение right должно соответствовать стандартам.

В классе Session nHibernate есть метод с именем Persist(object obj), с которым я поработал с шаблоном UnitOfWork - но из того, что я могу сказать, этот метод удаляет аспект отложенной загрузки любого приложения к. Если бы это было по отдельности, все было бы хорошо, но я понимаю, что не могу этого сделать. Я не могу общаться с моими Session напрямую - предполагается, что только моим Repository классам разрешено общаться с SessionFactory. Так что сейчас я действительно растерялся, растерянно.

1 Ответ

3 голосов
/ 17 декабря 2010

Вы должны передать ISession в конструктор класса репозитория. Шаблон сеанса для запроса обычно используется в веб-приложении, поэтому время жизни сеанса IS совпадает с HTTP-запросом. По моему мнению, классы репозитория никогда не должны обращаться к SessionFactory и всегда должны предоставлять ISession в качестве зависимости.

...