NHibernate:用于从存储库返回完全加载的实例的模式

时间:2010-07-19 18:40:42

标签: nhibernate design-patterns repository-pattern proxy-classes lazy-initialization

作为我无休止的受NHibernate启发的DAL重构炼狱的一部分,我已经开始使用Repository模式来保持NHibernate与我的UI层保持一定距离。以下是存储库中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;
}

但这一切似乎有点愚蠢。有没有人使用稍微优雅的模式?

爱你们。

大卫

4 个答案:

答案 0 :(得分:4)

使用依赖注入并通过其构造函数将ISession传递给存储库类。这是允许多个存储库参与同一事务的唯一方法。

您的网站应该具有ISession的一些知识,因为这是定义事务边界的地方。您可以使用每个请求的会话模式,以便仅在HttpRequest模块或Global.asax中引用ISession。或者您可以使用框架或拥抱NHibernate并控制页面上的事务。

答案 1 :(得分:1)

查看ncommon framework;它有一个很好的抓取策略实现,非常适合这种任务。您可以在author's blog上详细了解如何实施此功能。

我还应该注意你的会话使用情况有点偏离......你应该真正控制你的会话的生命周期更高(比如在控制器或httpmodule级别,具体取决于你的前端)。为每个存储库操作打开一个新会话是nhibernate世界中的一个主要反模式。

答案 2 :(得分:1)

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;
}

答案 3 :(得分:0)

部分问题是您使用 Session.Load()而不是 Session.Get()

看到这篇文章 Ayende Rahien - The difference between Get, Load and querying by id有关这两者的深入描述。

当您调用 Session.Load()时,您告诉nhibernate创建您提供的Id的代理对象。执行此操作时,nhibernate实际上不会调用数据库来检索数据。这意味着,如果 Session.Load()包含未在数据库中退出的内容,则会抛出异常。因为您在访问对象之前关闭了会话,所以无法访问数据,因为代理会话现已关闭。

一个简单的解决方法是将代码更改为使用 Session.Get()。这将从数据库加载StoredWill类,并使用所需的数据填充对象。但是请注意,如果您在对象内部有任何内部类或集合,它将只为这些创建代理。如果您需要一次性获取所有内容,则可以使用众多查询机制之一来急切加载您需要的部分或使用投影。

我希望这是有道理的:)