【发布时间】:2010-12-17 14:01:59
【问题描述】:
在 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 延迟加载代理 (
IList<Character>) Email
那么,我在我的Controller 中调用var member = memberRepository.RetrieveMember(email);,然后我调用member.Characters.Add(character); 这就是混乱的来源。
集合不存在,因为它是延迟加载的,
Session已被释放。
那么,答案是什么?当然,我可以将我的IList<Character> 设置为不延迟加载,但这有点愚蠢。如果阻碍了基本的设计结构,世界上最大的 ORM 库之一就不会使用延迟加载。 UnitOfWork 的这个概念如何在 IoC 的 IRepository<T> 模式和注入依赖中发挥作用?
我的第一个想法是将任务抽象到存储库,并在IMemberRepository 中包含一个AddCharacter(Character character) 方法,但我现在被告知“不是存储库的用途”。所以我不太确定从现在开始该怎么做。以编程方式我知道许多解决方案,但我需要了解正确解决方案是什么才能符合标准。
nHibernate 的 Session 类有一个名为 Persist(object obj) 的方法,我使用 UnitOfWork 模式进行了工作 - 但据我所知,此方法删除了任何它的延迟加载方面应用于。如果那是一个电话会议的基础,那会很好 - 但我知道我不能这样做。我不能直接与我的Session 交谈——只有我的Repository 类应该被允许与SessionFactory 通信。所以我现在真的很困惑。
【问题讨论】:
标签: asp.net-mvc nhibernate fluent-nhibernate castle-windsor lazy-loading