所有
我在对话和会话范围方面查看了Castle Active Record项目(在.net中)的来源。我得出结论,活动记录中的对话不能跨越不同的线程。换句话说,当我在线程A上创建对话而不是尝试在线程B上使用ConversationalScope(使用在线程A上创建的当前对话)时,我访问例如在线程AI上加载的实例上的惰性集合将获得异常因为检查当前线程作用域的SesessionFactoryHolder将找不到线程B的任何已注册作用域,因为每个线程(线程静态字段)存储了线程作用域(在窗体中)。
以上理解是否正确?如果是,那不是限制吗?对话应该能够跨越不同的线程。如果这是真的,我想问一些想法如何跨多个线程共享一个hibernate会话(使用Castle Active Record),而无需编写大量代码。
编辑:我想在这篇文章中添加我的最新发现。上述对话不跨越线程的陈述仍然适用。关于无法在另一个线程上加载惰性集合的声明是错误的。懒惰的集合可以懒惰地加载到另一个线程上(在这个例子中在线程B上)。我发现的原因是,只要会话存在,会话也会存在,因此可以访问惰性集合。编辑2:我明白了。我将把这个答案留给我的老帖子,以便对这个主题有疑问的其他人可以受益。
ANSWER :在城堡活动记录框架中,可以跨线程共享对话。会发生的事情是,在新线程上,会话范围始终使用以下行注册:
ConversationalScope scope = new ConversationalScope(currConv)
因此,当前线程具有有效的会话范围。然后强制SessionFactoryHolder使用线程的当前会话范围(而不是使用其本地会话)。检索hibernate会话的逻辑是它将此任务委托给会话,该会话将返回最后一个hibernate会话(在前一个线程A上创建)。因此,如果会话范围有效(未处理),则会获得由另一个线程创建的相同会话。
以下是示例代码:
Thread A: IScopeConversation conv = new ScopedConversation(); var order = null; using (ConversationalScope scope = new ConversationalScope(conv)) { order = Order.Load(1); } // spawn/run thread B, access lazy collection on order Thread B: using (ConversationalScope scope = new ConversationalScope(conv)) { IList orderDetails = order.Details; // will NOT cause exception since the conversation is still valid (has not been disposed) }
答案 0 :(得分:1)
在城堡活动记录框架中,可以跨线程共享对话。会发生的事情是,在新线程上,会话范围始终使用以下行注册:
ConversationalScope scope = new ConversationalScope(currConv)
因此,当前线程具有有效的会话范围。然后强制SessionFactoryHolder使用线程的当前会话范围(而不是使用其本地会话)。检索hibernate会话的逻辑是它将此任务委托给会话,该会话将返回最后一个hibernate会话(在前一个线程A上创建)。因此,如果会话范围有效(未处理),则会获得由另一个线程创建的相同会话。