NHibernate 坚持将对象添加到集合的顺序
我可能在这里犯了一个新手错误,但我不知道如何进行这项工作。我有两个实体 - Parent
和 Child
,其中一个 Parent
可以有多个 Child
ren。问题似乎是,当我向父级添加新子级时,父级无法级联保存子级,因为子级实例还没有 ID。另一方面,子项无法自行持久化,因此它无法获取 ID...
我的映射:
public ParentMap()
{
// ID and other properties
HasMany(p => p.Children).Cascade.AllDeleteOrphan().Not.LazyLoad();
}
public ChildMap()
{
// ID and other properties
References(c => c.Parent);
}
现在,我的数据库中可能已经有一条父记录,我想添加一条子项到其子项集合。为此,我创建了 Child
类的新实例,将子级添加到父级的 Children
属性(类型为 IList
)。我还获取父记录并将子级 Parent
属性设置为父实体。
当我尝试保存它时,无论我尝试按哪个顺序执行,都会出现错误。
使用Save(p)
,保存父记录并希望子记录能够级联保存,我收到以下错误:
无法将 NULL 值插入表“dbo.Children”的“ChildID”列;列不允许空值。插入失败。该声明已终止。
如果我尝试相反的方法,即首先保存子项,然后将其添加到父项并保存父项,则会出现以下错误:
Application.Domain.Entities.Child 条目中的 id 为空(发生异常后不刷新会话)
我应该按什么顺序调用 parent.Children.Add(child)
, child. Parent = Parent
、session.Save(parent)
和 session.Save(child)
以使此工作正常吗?我的映射配置中是否缺少某些内容?
更新:我添加了.Inverse()
,并尝试了以下操作但没有成功:
// First of the above errors
session.Save(child);
child.Parent = parent;
parent.Children.Add(child);
session.Save(parent);
// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(child);
session.Save(parent);
// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(parent);
// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(child);
I'm probably making a newbie mistake here, but I can't figure out how to make this work. I have two entities - Parent
and Child
, where one Parent
can have many Child
ren. The problem seems to be that when I add a new child to a parent, the parent can't cascade save the child, because the child instance doesn't have an ID yet. On the other hand, the child can't be persisted on its own, so it has no way of getting an ID...
My mappings:
public ParentMap()
{
// ID and other properties
HasMany(p => p.Children).Cascade.AllDeleteOrphan().Not.LazyLoad();
}
public ChildMap()
{
// ID and other properties
References(c => c.Parent);
}
Now, I might already have a parent record in my database, and I want to add a child to its collection of children. To do so, I create a new instance of the Child
class, add the child to the parent's Children
property (of type IList<Child>
). I also fetch the parent record and sets the childs Parent
property to the parent entity.
When I try to save this, I get errors no matter which order I try to do it.
With Save(p)
, saving the parent record and hoping the child will be saved on cascade, I get the following error:
Cannot insert the value NULL into column 'ChildID', table 'dbo.Children'; column does not allow null values. INSERT fails. The statement has been terminated.
If I try the other way around, i.e. first saving the child, then adding it to the parent and saving the parent, I get the following error:
null id in Application.Domain.Entities.Child entry (don't flush the Session after an exception occurs)
In what order should I call parent.Children.Add(child)
, child.Parent = parent
, session.Save(parent)
, and session.Save(child)
to make this work? Is something missing in my mapping configuration?
Update: I've added .Inverse()
, and tried the following without success:
// First of the above errors
session.Save(child);
child.Parent = parent;
parent.Children.Add(child);
session.Save(parent);
// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(child);
session.Save(parent);
// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(parent);
// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(child);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在父母一方将您的关系标记为
Inverse
。这会说 NHibernate 的子端管理关系:这迫使您手动设置
child.Parent =parent
,但无论如何您都会这样做,所以我相信这不是问题。默认情况下,NHibernate 假定父级有责任为子级设置外键。操作的逻辑顺序看起来像这样:
null
在您的第一个场景中,它在第 3 处失败,因为您没有可为空的外键列,并且 NHibernate 不够聪明,无法找到任何解决方案。
设置
Inverse()
告诉 Parent 不要关心 Child 外键,并且您有责任正确设置child.Parent
。在这种情况下保存时,只有 INSERT,如预期的那样,并且不会尝试在外键中设置null
。Mark your relation as
Inverse
on parent's side. This will say NHibernate that child's side manages the relation:This forces you to set
child.Parent = parent
manually, but you're doing it anyway, so I believe it's not a problem.By default, NHibernate assumes that it's parent's responsibility to set a foreign key on a child. And the logical order of operations look somehow like this:
null
in Parent's foreign keyIn your first scenario, it fails at no 3 as you have not nullable foreign key column and NHibernate is not smart enough to find any solution.
Setting
Inverse()
tells Parent to not care about Child foreign key and it's your responsibility to setchild.Parent
properly. On save in this case, there are only INSERTs, as expected and no tries to setnull
in foreign key.事实证明,问题根本不在于 NHibernate,而在于我的数据库配置 - 我忘记配置
Children
表的 ID 列。一旦我指定了 ID 列,一切都会按预期工作:不需要.Inverse()
,并且我可以只保存Parent
和Child 保存在级联中。
Turns out the problem wasn't with NHibernate at all, but rather with my database configuration - I had forgotten to configure the ID column of the
Children
table. As soon as I specified the ID column, everything worked as expected: no.Inverse()
needed, and I could save just theParent
and theChild
is saved on cascade.我缺少
Cascade.All()
和References
。我们不应该将Inverse()
放在HasMany
上:I was missing
Cascade.All()
withReferences
. We shouldn't putInverse()
onHasMany
: