我有一个NHibernate存储库类,它在单个事务中对多个表执行一些READ操作。
但我有一段旧代码试图在Parallel Threads上调用这个NHibernate类,比如
someList.AsParallel().Select(x=>x.repo.GetData());
操作失败说 SQL不支持多个事务,如何使NHibernate线程中的ISession安全?
答案 0 :(得分:4)
NHibernate ISession
不是线程安全的,周期
来自NHibernate参考文档Chapter 1, Getting started section:
ISession
是一个非线程安全对象,表示数据库的单个工作单元。
您应该改变旧的代码。
无论如何,这段代码看起来像编码恐怖。它遭受n + 1加载不良做法。通常这种情况发生时,延迟加载未正确设置(忘记在实体和集合的映射中设置足够的batch-size
,而没有设置default_batch_fetch_size
配置参数)。但在那里,它是明确编码的!
在循环中调用DB是一种性能反模式,您应该先修复它。在AsParallel
中调用它看起来只是原始开发人员尝试“优化”这种编码恐怖的不良尝试。
要修复它,您应该在一次调用中加载所有数据,然后根据需要将其分发到列表中。您可以先将数据投影到字典中,以避免使用O(n²)调度算法。
完成后,AsParallel
应该已经消失,您的线程安全也会出现问题。
如果事情太复杂(比你的例子显示的更多),或者真的对应于需要用并行性完成的事情,那么你应该为每个ISession
实例化一个专用的GetData
在您的并行处理中。
答案 1 :(得分:1)
请注意,使用延迟加载和代理时,甚至实体都是线程安全的!