简体   繁体   English

在流利的nHibernate中一对一模拟Cascade.AllDeleteOrphan

[英]Simulate Cascade.AllDeleteOrphan with one-to-one in fluent nHibernate

I have a parent table with an optional 1:1 relationship with a child table (the parent can exists without the child, but not vice-versa). 我有一个与子表具有可选 1:1关系的父表(该父表可以不带子表而存在,反之亦然)。 The auto-generated primary key of the parent table is used as the primary/foreign key of the child. 父表的自动生成的主键用作子级的主键/外键。

Thanks to a couple good references ( this question and this site ), I was able to get a working 1:1 relationship mapped out. 多亏了几个很好的参考资料( 这个问题本网站 ),我才得以绘制出一对一的工作关系。 I can create a parent with or without a child, update one or both, and deleting the parent cascades to delete the child, as expected. 我可以创建一个有或没有孩子的父母,更新一个或两个孩子,并删除父母级联以删除孩子。

However, I want to somehow 'simulate' the Cascade.AllDeleteOrphan() option of a HasMany mapping within my HasOne mapping structure, so that if the child end of the relationship is removed, the corresponding row in the child table will be deleted when the parent object is saved. 但是,我想以某种方式“模拟”我的HasOne映射结构中HasMany映射的Cascade.AllDeleteOrphan()选项,以便如果删除该关系的子级末尾,则当父对象已保存。 As is, if I try to remove the child manually, I understandably get a 'deleted object would be re-saved by cascade' error message. 照原样,如果我尝试手动删除该子级,我可以理解地得到'deleted object would be re-saved by cascade'错误消息。

Has anyone found a good way to do this while still only using HasOne mappings? 有没有人找到一种很好的方法来做到这一点,而仍然仅使用HasOne映射? Would what I am trying to do still even be a 1:1 relationship, or should I just be using one-to-many and rely on my database constraints and business logic to prevent multiple children? 我想做的甚至还是1:1的关系,还是我应该使用一对多并依靠我的数据库约束和业务逻辑来防止多个孩子?

Simplified code: 简化代码:

// 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();
            }
        }
    }
}

EDIT:: I have also tried the following code snippet, which is what gives me the 'deleted object would be re-saved by cascade' error message. 编辑::我还尝试了以下代码段,这就是给我“删除的对象将被级联重新保存”的错误消息的原因。

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

The cascade setting all-delete-orphan is not implemented in NHibernate, see NH-1262 . NHibernate中未实现级联设置all-delete-orphan,请参阅NH-1262 There is a pull request in a comment on the issue so it may come in a future version. 在对此问题的评论中有一个请求请求,因此它可能会在将来的版本中发布。

For now you can do: 现在,您可以执行以下操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM