0

作为我无尽的受 NHibernate 启发的 DAL 重构炼狱的一部分,我已经开始使用存储库模式来使 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

4 回答 4

4

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

您的网站应该对 ISession 有所了解,因为这是定义事务边界的地方。您可以使用 session-per-request 模式,以便仅在 HttpRequest 模块或 Global.asax 中引用 ISession。或者,您可以使用框架或采用 NHibernate 并控制页面上的事务。

于 2010-07-19T21:04:27.457 回答
1

查看ncommon 框架;它有一个很好的获取策略的实现,非常适合这类任务。你可以在作者的博客上阅读更多关于这是如何实现的。

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

于 2010-07-19T18:57:21.377 回答
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;
}
于 2010-07-19T19:05:50.517 回答
0

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

请参阅 Ayende Rahien 的这篇文章 - Get、Load 和 querying by id 之间的区别,以深入了解这两者。

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

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

我希望这是有道理的 :)

于 2011-02-21T00:24:38.803 回答