所以,我的父对象上有一个子列表,我希望将它们保存在我的SQL Server上。当我第一次运行应用程序时,所有的孩子都正确地获得了他们的FK,但是当我再次运行它并且没有添加新的父项时,新的孩子(现有的父母)没有得到它#39;父FK,只是NULL。对于那些情况,如何在子映射上映射父FK?
我已经尝试了Inverse()
方法,但是因为我需要生成父键,所以所有子节点都会为null。我需要类似的东西,如果父母是新的,那么父母会更新它的孩子FK,但是当只有孩子是新的时我会需要它来做Inverse()
方法,是否可能? / p>
更多信息:
每次我调用ParentPersist方法时,它都会根据需要进行级联。当新的子项添加到列表中时,我添加了AddChild()
方法来设置 ParentId ,它在调试时正常工作,所以孩子正在设置它的ParentId正确。
对象如下:
public class Parent
{
public virtual int Id { get; set; }
...
public virtual IList<Child> Children{ get; set; }
public virtual void AddChild(Child ch)
{
ch.IdParent = this.Id;
Children.Add(ch);
}
}
public class Child
{
public virtual int Id { get; set; }
...
public virtual int IdParent {get;set;}
}
我的映射:
public class ParentMapping : ClassMap<Parent>
{
public ParentMapping ()
{
Id(cso => cso.Id).GeneratedBy.Identity();
...
HasMany(cso => cso.Children).KeyColumn("IdParent").Cascade.SaveUpdate().Not.LazyLoad();
}
}
public class ChildMapping : ClassMap<Child>
{
public ChildMapping ()
{
Id(cso => cso.Id).GeneratedBy.Identity();
...
}
}
答案 0 :(得分:1)
您的逻辑(例如,父Add()
映射中的Inverse()
方法)是正常的。你快到了。只有一个但是......
一般来说,正确的(如果不仅仅是正确的)解决方案是使用对象表达实现和 不 ValueType / int值 。这就是我们称之为ORM - Object-relational mapping
C#中的对象应如下所示:
public class Parent
{
...
// correct mapping of the children
public virtual IList<Child> Children{ get; set; }
// this method uses the below updated Child version
public virtual void AddChild(Child ch)
{
// this is replaced
// ch.IdParent = this.Id;
// with this essential assignment
ch.Parent = this;
Children.Add(ch);
}
}
public class Child
{
...
// instead of this
// public virtual int IdParent {get;set;}
// we need the reference expressed as object
public virtual Parent Parent { get; set; }
}
所以,现在,一旦我们有了对象,我们可以像这样调整映射:
// parent
public ParentMapping ()
{
...
HasMany(cso => cso.Children)
.KeyColumn("IdParent")
.Inverse() // this is essential for optimized SQL Statements
.Cascade.SaveUpdate() // All delete orphan would be better
.Not.LazyLoad();
}
...
// Child
public ChildMapping ()
{
...
References(x => x.Parent, "IdParent"); // it is a to use Inverse()
}
使用此业务领域模型和映射(Inverse()
,分配关系以Add()
方法...)结束,NHibernat将始终拥有足够的信息(插入,update)发出适当的SQL语句
注意:有人可能会问为什么要映射Parent Parent { get; set; }
而不仅仅是int IdParent { get; set; }
...实际上,如果我们有现有的Parent(非临时ID,即{{1} }) - 没有任何区别。诀窍/问题将出现在> 0
插入上。几乎总是,孩子们在父母被贬低(冲洗)之前就已经分配了,并且从ID(sql server身份)收到了她的ID。这可能/会导致new Parent
...
我们应该记住,一般来说 - ORM是关于对象的,即关系由引用类型表示。