NHibernate保存子元素FK为NULL

时间:2014-11-15 21:22:37

标签: c# nhibernate null fluent-nhibernate fluent

所以,我的父对象上有一个子列表,我希望将它们保存在我的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();
        ...
    }
}

1 个答案:

答案 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是关于对象的,即关系由引用类型表示。