仅通过nhibernate保存父对象的子对象有时会导致不将子对象插入表中。 这种情况大部分时间都有效,而且只有成千上万次,孩子失踪了。
这是一个大型多线程应用程序。
以下是子映射:
<class name="Child" table="children" lazy="false" optimistic-lock="all" dynamic-update="true">
<id name="Id" column="id">
<generator class="native" />
</id>
<many-to-one name="MyParent" class="Parent" column="parent_id" not-null="true"/>
...
...
和儿童班:
public class Child
{
public long Id { get; set; }
public Parent MyParent { get; set; }
...
..
父映射:
<id name="Id" column="id">
<generator class="native" />
</id>
<set name="Children" table="children" cascade="none" lazy="true" inverse="true">
<key column="parent_id" not-null="true" />
<one-to-many class="Child" />
</set>
...
...
以下是父类
public class Parent
{
public long Id { get; set; }
public ICollection<Child> Children { get; set; }
...
...
..
}
添加父母和孩子的代码如下所示:
var theParent = new Parent
{
...
}
...
// start the transaction if not begun by the caller
// a few lines later...
Session.Save(theParent);
// Commit transaction only if this method began the transaction...
...
var child = new Child
{
MyParent = theParent,
...
...
}
...
// start the transaction if not begun by the caller
// a few lines later...
Session.Save(child);
// Commit transaction only if this method began the transaction...
// make sure the two-way associations are updated!
if (!child.MyParent.Children.Contains(child))
child.MyParent.Children.Add(child);
...
检查调用者是否已开始事务的机制似乎没有任何错误,并且调用者不会在不抛出异常并记录它的情况下回滚。我没有找到任何回滚的交易痕迹。
在任何一种情况下,为什么孩子只在少数情况下失踪。这很难处理,并且可能会在生产中无声地造成很多问题。造成这种情况的原因是什么?
答案 0 :(得分:1)
我敢打赌你的交易处理机制有一个缺陷,而且交易有时根本没有提交。它最终收集垃圾,导致它被静默处理和滚动。如果在事务提交之前发生会话conf/log4j.properties
,则会发生这种情况。
您可以通过记录事务启动/提交/回滚以及相关的上下文信息来跟踪它,以便与提交和回滚进行匹配。
这可能非常棘手。什么是相关的背景信息?它在很大程度上取决于应用类型在IIS下的Web应用程序中,线程上下文不好,调用上下文不好。在asp.net线程敏捷切换的情况下,它们都会丢失,这会在负载下发生。在大多数情况下,仅保留HTTP上下文。 (并注意Close
配置“回调”配置为在没有任何上下文的情况下运行...)