如何在NHibernate中将会话作为工作单元进行管理?

如何在NHibernate中将会话作为工作单元进行管理?,nhibernate,unit-of-work,Nhibernate,Unit Of Work,在Winforms和WPF中使用NHibernate几年之后,我似乎仍然忽略了一个非常重要的点,当我运行此代码片段时,这一点变得太明显了: ISessionFactory sf = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008 .ConnectionString(c => c.Is(conne

在Winforms和WPF中使用NHibernate几年之后,我似乎仍然忽略了一个非常重要的点,当我运行此代码片段时,这一点变得太明显了:

 ISessionFactory sf = Fluently.Configure()
                              .Database(MsSqlConfiguration.MsSql2008
                                .ConnectionString(c => c.Is(connectionString)))
                              .Mappings(x => x.FluentMappings
                                .AddFromAssemblyOf<MyClass>())
                              .BuildSessionFactory();

 for (int i = 0; i < 100; i++)
 {
     new Task(()=>
     {
         Console.WriteLine("{0}, {1}",
           i, 
           sf.OpenSession().QueryOver<MyClass>().List().Count);
     }).Start();
 }
ISessionFactory sf=Fluently.Configure()
.数据库(MsSqlConfiguration.MsSql2008
.ConnectionString(c=>c.Is(ConnectionString)))
.Mappings(x=>x.FluentMappings
.AddFromAssemblyOf())
.BuildSessionFactory();
对于(int i=0;i<100;i++)
{
新任务(()=>
{
Console.WriteLine(“{0},{1}”,
我
sf.OpenSession().QueryOver().List().Count);
}).Start();
}
我猜想这会造成很大的负担

老实说,我记得读过的关于会话处理的唯一一件事是:实现工作单元,它宣布atomar会话。因此,我有一些顾虑/问题

  • 延迟加载在图片中的效果如何?如果我使用一个会话加载数据,然后关闭它,延迟加载将不起作用。因此,基本上,工作单元不能关闭/处理会话,这意味着它是无限大的

  • 会话具有类似于
    IsDirty
    的功能。如果加载和保存对象是通过单独的会话完成的,那么如何仍然利用这些会话

编辑:奥伦·埃尼(Oren Eini)在其早年曾说过同样的问题。在那里,他说微观管理(>使用和立即
处置
)切断了NH的功能,如懒散加载和变更跟踪。但在我看来,UnitOfWork是一种会话微观管理模式。那么,什么是最干净的解决方案?自己跟踪变化并使用微观管理?单片会话(=设计的Memleak)?与Oren的示例不同,如果没有太多可以限制会话生存期的子对话框,该怎么办

延迟加载在图片中的效果如何

延迟加载适合一个会话的情况。加载对象后,延迟加载允许遍历对象的图形,而无需知道对象属性是否已从数据库加载,也无需急于加载所有对象图形

看起来很完美,但也有一些问题,比如“n+1选择”

如果我使用一个会话加载数据,然后关闭它,延迟加载将不起作用

从db加载同一对象的另一个会话将不会从上一个会话中加载的属性中受益

因此,基本上,工作单元不能关闭/处置会话, 意味着它是无限大的

我不确定我是否理解这一点。我想会话是工作的单位

会话具有像IsDirty这样的特性。 如果加载和保存对象是通过单独的会话完成的,那么如何仍然利用这些会话

加载和保存不应在单独的会话中完成。我想这就是IsDirty属性的要点

这可能会为您提供许多有关NH处理的提示:

希望这会有所帮助

编辑:关于你的第二个问题。通常的web场景如下所示:

  • 打开NH会话
  • 加载NH实体
  • 在POCO中传输NH实体属性以在UI中显示(当然要跟踪Id)
  • 关闭NH会话
  • 稍后(用户进行了一些更改并点击“保存”按钮),打开NH会话
  • 加载相应的NH实体(通过其Id)
  • 根据新的POCO字段更新NH实体
  • 在数据库中保存更改
  • 关闭NH会话

  • 1、2和4是第一个工作单元的组成部分。5、6、7、8和9是第二个工作单元的组成部分

    工作单元不是无限大,会话也不是无限大(会话是工作单元)。工作单元是atomar,做一些属于一起的事情,在这个单元中,您使用延迟加载。你的代码应该做什么?没有工作单元,因为根本没有工作,只有一个查询。@StefanSteinegger我说的是与UI相关的问题。在许多情况下(主详细视图),您将主干数据绑定到列表控件,当用户选择一个项时,延迟加载并将其结果绑定到子视图。这可能发生在初始加载数小时后。这是我应该避免的。将UI绑定到实体会带来麻烦。它不允许任何业务逻辑层。你不知道一个工作单元什么时候开始和结束。将事务绑定到UI时,数据库中会出现巨大的锁定问题。在NH代理和数据绑定等方面,你也会遇到一些问题,除了“你无法判断一个工作单元何时开始和何时结束”,我完全同意。实际上,MVVM模式就是这样工作的。即使您将模型本身绑定到UI,或者将它们保存在引用它们(并使用延迟加载)的某个存储库中,以生成用于在UI中绑定的其他实体,这都无关紧要——会话必须打开很长时间,这让我回到了我最初的问题。MVVM/延迟加载和工作单元可以统一吗?感谢您的回复。我大致了解延迟加载的原理,请看问题的第二条评论,我解释了我的意思。那么,基本上,你说应该使用相同的会话加载和保存?“我经常这样做,但如果我理解正确的话,这与工作单元模式有点相反,不是吗?”SebastianEdelmeier添加了一个关于加载和保存的常见场景。希望这会有帮助,谢谢你的例子。它实际上描述了我的问题。延迟加载意味着:在需要时查询数据。如上所述,在UI中,查询可能比原始查询晚一段时间。这就是为什么我的意思是,在启用延迟加载的情况下,工作单元会增长到无限/不确定的大小。但是你的样品有另一个我到目前为止没有使用的问题(请更正m)