【发布时间】:2009-11-27 14:16:17
【问题描述】:
我有两个相关的对象:ProgramSession 和 ProgramTask,具有一对多的关系。一个 ProgramSession 有许多 ProgramTask。所以对象看起来像这样:
public class ProgramSession
{
public virtual IList<ProgramTask> ProgramTasks
{
get { return _programTasks; }
set { _programTasks = value; }
}
}
public class ProgramTask
{
public virtual ProgramSession ProgramSession
{
get { return _programSession; }
set { _programSession = value; }
}
}
还有映射...
ProgramSession.hbm.xml
<bag name="ProgramTasks" lazy="false" cascade="all-delete-orphan" inverse="true" >
<key column="SessionUid"></key>
<one-to-many class="ProgramTask"></one-to-many>
</bag>
ProgramTask.hbm.xml
<many-to-one name="ProgramSession" column="SessionUid" class="ProgramSession" />
当我尝试更改 ProgramTask 的 ProgramSession 时,问题就开始了。
如果我从旧会话的 ProgramSession.ProgramTasks 列表属性中删除 ProgramTask,然后将其添加到新会话的相同属性中,NHibernate 会告诉我将重新保存已删除的对象。
如果我只是简单地更改 ProgramTask.ProgramSession 对象的值,则保存没有问题。但是,如果我不立即保存,我会出现奇怪的行为,因为 ProgramSession.ProgramTasks 属性(在两个会话上)直到 NHibernate 会话刷新后才会同步。
更改 ProgramTask.ProgramSession 对象而不直接修改列表也会创建无效状态。以如下代码为例:
programTask.ProgramSession = newProgramSession;
Assert.That(newProgramSession.ProgramTasks.Contains(programTask)); // fails
Assert.That(!oldProgramSession.ProgramTasks.Contains(programTask)); // fails
这在稍后执行的代码中更成问题,假设 ProgramTasks 集合与 ProgramSession 属性同步。例如:
foreach(var programTask in programSession.ProgramTasks)
{
// whatever
}
我用来解决这个问题的一个技巧是查询列表。我不能到处使用它,这显然是一个糟糕的解决方案,但它强调了问题:
var tasksActuallyInSession =
programSession.ProgramTasks
.Where(task => task.ProgramSession == programSession)
.ToList();
有没有办法处理这种情况?最佳实践?难道我做错了什么?映射不正确?我需要设置一些超级机密的 NHibernate 标志吗?
【问题讨论】:
-
我相信你的意思是把属性放在你在问题中定义的类中。
-
你是对的。感谢您的提醒。
标签: nhibernate collections nhibernate-mapping