Учитывая довольно простую структуру в 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
. Так что сейчас я действительно растерялся, растерянно.