2011-07-25 29 views
3

我可能在这里做一个新手的错误,但我无法弄清楚如何使这项工作。我有两个实体 - ParentChild,其中一个Parent可以有许多Child ren。问题似乎是,当我向父项添加新子项时,父项不能级联保存子项,因为子项实例尚未具有ID。在另一方面,孩子不能在自己的坚持,所以它没有获得一个ID的方式...NHibernate的坚持为了增加对象集合

我的映射:

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<Child>)。我还获取父记录并将子女Parent属性设置为父实体。

当我试图挽救这个,我得到的错误,无论我尝试做顺序。

随着Save(p),节约父记录,希望孩子将被保存在级联,我得到以下错误:

Cannot insert the value NULL into column 'ChildID', table 'dbo.Children'; column does not allow null values. INSERT fails. The statement has been terminated.

如果我试着在其他的方式,即先救孩子,然后加入它的母公司和保存的父母,我得到以下错误:

null id in Application.Domain.Entities.Child entry (don't flush the Session after an exception occurs)

按照什么顺序我应该叫parent.Children.Add(child)child.Parent = parentsession.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); 

回答

0

原来,NHibernate根本不是这个问题,而是我的数据库配置 - 我忘记了配置Children表的ID列。只要我指定ID列,一切都按预期工作:不需要.Inverse(),我可以只保存ParentChild级联保存。

0

标记您的父母的一侧Inverse关系。这会说NHibernate的那个孩子的侧管理的关系:

HasMany(p => p.Children).Cascade.AllDeleteOrphan().Not.LazyLoad().Inverse(); 

这将迫使你手动设置child.Parent = parent,但你无论如何做,所以我相信这不是一个问题。

默认情况下,NHibernate的假定它的父的责任来设置对孩子的外键。和操作的逻辑顺序看某种程度上是这样的:

  1. 家长要保存
  2. 儿童由于保存级联 - 我们没有父ID,但(至少我们不能有,我不知道为什么它的工作原理是,当我们知道它,太)
  3. 孩子们在家长的外键
  4. 家长与null插入,然后插入成功,其ID被取出
  5. 孩子有父母的外键更新。

在你的第一种情况下,它没有在3号,因为你没有可以空的外键列和NHibernate不够聪明,找到任何解决方案。

设置Inverse()告诉家长不关心子外键,您有责任正确设置child.Parent。保存在这种情况下,只有插入,如预期的那样,并且不会尝试在外键中设置null

+0

随着'.Inverse()'如你所说,我仍然得到完全相同的错误。 –

0

我失踪Cascade.All()References。我们不应该把Inverse()HasMany

public ParentMap() 
{ 
    // ID and other properties 

    HasMany(p => p.Children).Cascade.AllDeleteOrphan().Not.LazyLoad(); 
} 

public ChildMap() 
{ 
    // ID and other properties 

    References(c => c.Parent).Cascade.All(); 
}