将断开连接的对象附加到NHibernate会话; 最佳实践?

Kei*_*thS 14 c# nhibernate

我的存储库在UnitOfWork模型中工作; 所有操作,无论是检索还是持久性,都必须在IDisposable UnitOfWork令牌对象的范围内执行,后者在后面与Session执行请求的工作相关联.所以,基本模式是:

using (var uow = repo.BeginUnitOfWork())
{
   try
   {
      //DB operations here; all repo methods require passing in uow.
      ...
      repo.CommitUnitOfWork(uow);
   }
   catch(Exception)
   {
      repo.RollbackUnitOfWork(uow);
      throw;
   }
}
Run Code Online (Sandbox Code Playgroud)

我还实现了一些包装器方法,允许您指定将在此框架中执行的lambda或委托,从而减少每次都需要实现所有这些脚手架的需要.

我遇到的问题是使用这个模型,代码必须"知道"用户需要什么,并NHUtil.Initialize()在内部使用它来急切加载它UnitOfWork.一旦UOW被放置在使用块的末尾,与any关联的Session PersistentBags就会关闭,因此无法对它们进行评估.由于急切加载所有事情并不总是可行的,并且有点破坏了延迟加载ORM的目的,我正在实现一种Attach()方法.

这是问题; 在没有内置ISession.Attach()方法的情况下,我看到有三种方法建议将对象与新的Session相关联.完成工作的最佳做​​法是哪一项?

A:

if(!Session.Contains(domainObject))
    Session.Update(domainObject);
Run Code Online (Sandbox Code Playgroud)

B:

Session.Merge(domainObject);
Run Code Online (Sandbox Code Playgroud)

C:

Session.Lock(domainObject, LockMode.None);
Run Code Online (Sandbox Code Playgroud)

Jam*_*Ide 24

D:以上都不是.通过保持你的UOW太短而有效地禁用延迟加载并且无法实现延迟加载ORM的目的.您必须将断开连接的对象重新关联为正常操作,这意味着您的工作单元边界是错误的.

合并,更新和锁定都有不同的用途.如果您坚持使用当前的架构,那么Lock可能就是您想要的.

  • 更新 - 关联已更改的对象
  • 锁定 - 关联未更改的对象
  • 合并 - 如果对象存在于当前会话中,则使用合并对象的更改进行更新,否则它与Lock相同

  • 为了增加Jamie的答案,我认为这正是每个请求工作单元方法如此广泛使用的原因(如果您正在使用Web应用程序).基本上,你实现了一个IHttpModule,它在application_BeginRequest上打开你的UOW,然后在application_EndRequest上你提交你的更改(或者如果出现错误则返回UOW),然后根据需要进行处理.这样,会话/ UOW处理应完全封装您的用户代码,您不必担心运行未初始化的代理等. (3认同)