Fluent NHibernate ISessionManager或同等级别

本文关键字:NHibernate ISessionManager Fluent | 更新日期: 2023-09-27 18:00:53

我对FNH和NH世界很陌生,所以要温和:p

我已经创建了一个使用FNH进行数据访问的应用程序,它在不使用延迟加载的情况下运行良好,但一旦我启用了延迟加载,一切都会变成梨形(如中所示,当我尝试访问延迟加载的属性时,没有会话打开等(。

到目前为止,我创建的应用程序布局有一个"Database"单例,它有各种方法,如Save((、Refer((和List((
当调用Refer((时,打开一个会话,检索数据并处理该会话;这意味着当试图从返回的对象访问延迟加载的属性时,没有可用的会话。示例:数据库。请参阅("用户名"(。Person,因为Person是惰性加载的,并且会话已经关闭。

我读到Castle有一个SessionManager,可以用于这种情况,但无论是深夜还是缺少咖啡,我似乎都不知道如何连接FNH来使用这个管理器,因为本着Castle的精神,一切都在配置文件中定义。

我是错过了什么,还是不能这样做?我是否应该考虑其他会话管理器(甚至更合适的约定(?

谢谢你在这件事上的帮助。

Fluent NHibernate ISessionManager或同等级别

我不认为您的特定问题与SessionManager有关,因为您已经提到您能够启动新会话并在需要时处理它。

根据我对你的帖子的理解,你试图将一个实体暴露在你的视图中(带有一些懒惰加载的属性(——这已经是一个坏主意,因为它会导致令人讨厌的LazyInitializationException(s)

您应该考虑区分您的data-modeldomain model。这个博客描述了关键概念:

Ayende@Raheenhttp://ayende.com/blog/4054/nhibernate-query-only-properties

如果您说您正在编写一个非常简单的2层应用程序,那么如果您在数据层中对会话进行微观管理(,但请记住,这不是最好的解决方案(,可能不会有什么害处。

我还将研究获取实体的查询,因为在我看来,您试图获取的数据只是模型的一部分——在本例中为Person。这可能会导致严重的问题,如n+1 selects:

什么是SELECT N+1?

因此,总的来说,我认为您应该更多地关注应用程序中事物的结构,而不是搜索SessionManager,因为它不会解决所有问题。

对于任何仍在寻找答案的人,我将与您分享我迄今为止所拥有的。

这只是我决定使用的框架的一个非常简单的概述,并不是这个问题的唯一解决方案。

我的代码的基本布局如下:

  • NHibernate存储库(参考我的模型部件和UoW部件(
    • 基于HibernatingRhino的Repository实现进行了修改,以满足我的需求。在此处找到:http://ayende.com/Wiki/Rhino+Commons.ashx
      public T Get(Guid Id)
      {
          return WrapUOW(() =>
          {
              using (Audit.LockAudit())
                  return (T)Session.Get(typeof(T), Id);
          });
      }
      public void LoadFullObject(T partial)
      {
          if (partial == null)
              throw new ArgumentNullException("partial");
          if (partial.Id == Guid.Empty)
              return;
          WrapUOW(() =>
          {
              using (Audit.LockAudit())
              {
                  LazyInitialiser.InitialiseCompletely(partial, Session);
              }
          });
      }
      public T SaveOrUpdate(T entity)
      {
          using (Audit.LockAudit())
          {
              With.Transaction(() =>
              {
                  Enlist(entity);
                  Session.SaveOrUpdate(entity);
                  entity.HasChanged = false;
              });
          }
          return entity;
      }
      protected void Enlist(T instance)
      {
          if (instance != null && instance.Id != Guid.Empty && !Session.Contains(instance))
              using (Audit.LockAudit())
              {
                  Session.Update(instance);
              }
      }
      
      
    • References a neat little helper class called 'Lazy Initializer for NHibernate' found here: http://www.codeproject.com/KB/cs/NHibernateLazyInitializer.aspx
    • This also contains Extension methods for Save, Delete and LoadFullObject
    • Have broken standards a little in this assembly by also creating a WrapUOW method to help simplify some of my code
      protected static T WrapUOW(Func action)
      {
          IUnitOfWork uow = null;
          if (!UnitOfWork.IsStarted)
              uow = UnitOfWork.Start();
          T result = action();
          if (uow != null)
              uow.Dispose();
          return result;
      }
  • NHibernate工作单元(参考我的模型部件(
    • 同样基于HibernatingRhino的UoW实现,并进行了修改以适应
  • 视图-不重要,只是MVVM实现所需
    • 绑定ViewModel中的值
  • 型号
    • 包含我的实体类和hibernate映射文件
  • ViewModel
    • 包含两个主要视图基类,ListPage和MaintenancePage
    • ListPage基类只是根据我们列出的对象类型调用RepositoryList方法。这将加载实体的脱水列表
    • MaintenancePage从ListPage获取一个实体实例并调用Repository。LoadFullObject方法来重新水合实体以在屏幕上使用。
      • 这允许在屏幕上使用绑定
      • 我们也可以安全地调用存储库。此页面中的SaveOrUpdate方法