自定义NHibernate会话实现

自定义NHibernate会话实现,nhibernate,session,Nhibernate,Session,我正在开发一个使用NHibernate执行批量处理的系统。我知道NHibernate不是为批量处理而设计的,但是由于进行了大量优化,该系统工作得非常好 处于最低粒度级别的对象(即聚合的根)具有许多字符串属性,这些属性不能(或者说,没有意义)根据自己的需要(例如“注释”)建模。事实上,数据库中与这些属性对应的字段只接受这么多的值(例如,因为大多数(但不是全部)注释都是机器生成的),结果是,当对大量对象进行水合处理时,成千上万个具有相同值的字符串实例会浪费大量内存 我在考虑通过创建自己的NHiber

我正在开发一个使用NHibernate执行批量处理的系统。我知道NHibernate不是为批量处理而设计的,但是由于进行了大量优化,该系统工作得非常好

处于最低粒度级别的对象(即聚合的根)具有许多字符串属性,这些属性不能(或者说,没有意义)根据自己的需要(例如“注释”)建模。事实上,数据库中与这些属性对应的字段只接受这么多的值(例如,因为大多数(但不是全部)注释都是机器生成的),结果是,当对大量对象进行水合处理时,成千上万个具有相同值的字符串实例会浪费大量内存

我在考虑通过创建自己的NHibernate自定义类型来透明地优化此场景,该类型通过重写
NullSafeGet()
并执行字典查找来反复返回每个字符串出现的相同实例,从而增强了NHibernate的
StringType
。换言之,我会自己练习一种弦乐。通过使用自定义类型,我只需在映射文件中指定该类型,就可以选择应该“插入”哪些对象的哪些属性

理想情况下,我希望将此字典“粘贴”到会话中,以便此字符串池的生存期与第一级缓存的生存期绑定。毕竟,从我们的系统的角度来看,在初始化会话及其一级缓存的同时初始化这个字符串池是有意义的,在关闭会话的同时对字符串池进行核爆也是有意义的。通过拥有自己的私有字典,并发会话彼此完全隔离也是一个可取的特性

问题是,除了创建我自己的NHibernate代码分支之外,我找不到一种方法将NHibernate会话的自定义实现“注入”到NHibernate本身,以便
IType
可以在
NullSafeGet()
时间访问它


有没有办法为NHibernate提供自定义会话实现?

我看到三种不同的方法可以解决这个问题:

1。使用拦截器

在IInterceptor中,您可以获得:

void AfterTransactionBegin(ITransaction tx);
void BeforeTransactionCompletion(ITransaction tx);
2。结束打开和关闭会话:

打开和关闭会话是一个显式调用。将其封装到方法中应该很容易

public ISession OpenSession()
{
  var session = sessionFactory.CreateSession();
  StringType.Initialize();
}
你可以做得更好。我编写了一个事务服务,它包含事件。然后您可以处理开始事务和结束事务事件

3。不要将字符串缓存附加到会话

它不需要与会话相关。字符串是不可变的对象,当您在会话之间混合它们时不会有任何影响。为了避免缓存无限增长,您可以编写自己的缓存或使用现有的“最近使用的”缓存。长大到一定尺寸后,它会扔掉最古老的物品


这可能需要一些时间来实现,但非常好用。

我看到三种不同的方法来解决这个问题:

1。使用拦截器

在IInterceptor中,您可以获得:

void AfterTransactionBegin(ITransaction tx);
void BeforeTransactionCompletion(ITransaction tx);
2。结束打开和关闭会话:

打开和关闭会话是一个显式调用。将其封装到方法中应该很容易

public ISession OpenSession()
{
  var session = sessionFactory.CreateSession();
  StringType.Initialize();
}
你可以做得更好。我编写了一个事务服务,它包含事件。然后您可以处理开始事务和结束事务事件

3。不要将字符串缓存附加到会话

它不需要与会话相关。字符串是不可变的对象,当您在会话之间混合它们时不会有任何影响。为了避免缓存无限增长,您可以编写自己的缓存或使用现有的“最近使用的”缓存。长大到一定尺寸后,它会扔掉最古老的物品


这可能需要一些时间来实现,但非常好用。

谢谢Stefan,事实上,我认为3号是最可行的选项。我编辑了我的问题,补充说理想情况下,并发会话应该完全隔离,也可以使用单独的字典。如果我不能通过将字典“并置”到一个会话来实现这种隔离,那么#3和一个静态的类似MRU的字典将一针见血。谢谢Stefan,事实上,我认为3是最可行的选择。我编辑了我的问题,补充说理想情况下,并发会话应该完全隔离,也可以使用单独的字典。如果我不能通过将字典“并置”到一个会话来实现这种隔离,那么#3和一个静态的类似MRU的字典就会一针见血。