1

我有一个父表,它与子表具有可选的1:1 关系(父表可以在没有子表的情况下存在,反之亦然)。父表自动生成的主键用作子表的主/外键。

多亏了几个很好的参考资料(这个问题这个网站),我才能够绘制出一个有效的 1:1 关系。我可以创建一个有或没有孩子的父母,更新一个或两个,并删除父级联以删除孩子,正如预期的那样。

但是,我想以某种方式“模拟”我的映射结构Cascade.AllDeleteOrphan()中的映射选项,以便如果删除关系的子端,则在保存父对象时将删除子表中的相应行。照原样,如果我尝试手动删除孩子,我会收到一条错误消息,这是可以理解的。HasManyHasOne'deleted object would be re-saved by cascade'

有没有人找到一个很好的方法来做到这一点,同时仍然只使用HasOne映射?我想要做的仍然是 1:1 的关系,还是应该只使用一对多并依靠我的数据库约束和业务逻辑来防止多个孩子?

简化代码:

// Parent class
public partial class Parent
{
    public int pkParentID { get; set; }
    public Child child { get; set; }
    public Parent() { }
}

// Child class
public partial class Child
{
    public int pkParentID {get; set; }
    public Parent parent { get; set; }
    public Child() { }
    public Child(Parent parent) { this.parent = parent; }
}

// Parent mapping
public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        Table(@"Parent");
        LazyLoad();
        Id(x => x.pkParentID)
          .Column("pkProjectID")
          .Not.Nullable()
          .GeneratedBy.Identity();
        HasOne<Child>(x => x.Child)
          .PropertyRef(r => r.Parent)
          .Cascade.All();
    }
}

// Child map
public class ChildMap :ClassMap<Child>
{
    public ChildMap()
    {
          Table(@"Child");
          LazyLoad();
          Id(x => x.pkParentID, "pkParentID") 
            .GeneratedBy.Foreign("Parent");
          HasOne<Parent>(x => x.Parent)
            .Constrained()
            .ForeignKey()
            .Cascade.None();
    }
}


// Ideally, the code snippet below would remove the row from the Child table
Parent parent = service.GetById(uniqueID);
if (parent.Child != null)
    parent.Child = null;
service.SaveOrUpdate(parent);


// Just in case, here's my repository code
public virtual void SaveOrUpdate(T entity)
{
    ISession _session = NHibernateSessionProvider.GetSession();
    if (!_session.Transaction.IsActive)
    {
        using (ITransaction transaction = _session.BeginTransaction())
        {
            try
            {
                _session.SaveOrUpdate(entity);
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
            }
        }
    }
}

编辑:: 我还尝试了以下代码片段,这就是给我“已删除的对象将被级联重新保存”错误消息的原因。

...
Parent parent = parentService.GetById(uniqueID);
if (parent.Child != null)
{
    childService.Remove(parent.Child);  // this gives the above error
    parent.Child = null;
}
4

1 回答 1

0

级联设置 all-delete-orphan 在 NHibernate 中没有实现,请参阅NH-1262。关于该问题的评论中有一个拉取请求,因此它可能会出现在未来的版本中。

现在你可以这样做:

Parent parent = service.GetById(uniqueID);
parent.Child = null;
service.Delete(parent.Child); // probably needs to occur in a different repository
// commit transaction or flush session, there's no need to call SaveOrUpdate
于 2013-02-06T16:00:08.677 回答