NHibernate使用删除级联从父集合中删除子级

时间:2015-05-15 17:12:24

标签: c# nhibernate fluent-nhibernate

我有两个名为Country和City的简单实体。

public class Country : Entity
{
    public Country()
    {
        Cities = new List<City>();
    }

    public virtual string Name { get; set; }
    public virtual IList<City> Cities { get; set; }
}

public class City : Entity
{
    public virtual Country Country { get; set; }
    public virtual string Name { get; set; }
}

使用的数据库是SQL Server,城市有一个带有级联删除的国家/地区的外键。

我正在使用Fluent NHibernate,这是关系的映射配置:

public CountryMap()
    {
            Id(x => x.Id, "IdCountry").GeneratedBy.Identity();

            Map(x => x.Name).Not.Nullable().Length(50);

            HasMany(x => x.Cities).KeyColumn("IdCountry").ForeignKeyConstraintName("FK_Cities_Countries")
                .Not.KeyNullable().Cascade.AllDeleteOrphan().ExtraLazyLoad();

            Table("Countries");
    }

public CityMap()
    {
            Id(x => x.Id, "IdCity").GeneratedBy.Identity();

            Map(x => x.Name).Not.Nullable().Length(50);

            References(x => x.Country, "IdCountry").ForeignKey("FK_Cities_Countries")
                .Not.Nullable().Not.Insert().Not.Update().Cascade.All().LazyLoad();


            Table("Cities");
    }

一切正常,但删除国家/地区后,城市仍保留在父系列中,我希望从该系列中删除城市。 (正如EF所做的那样)

我找到让它运作的唯一方法是刷新会话(Clear,Evict ......)

2 个答案:

答案 0 :(得分:1)

使用这种映射,最简单的方法是从Country集合中删除City并保存Country。通过级联,城市将被删除,收集将处于您想要的状态。

答案 1 :(得分:1)

手动删除收集项目不是解决方案。它实际上打破了cascading功能。

如果我们确实有 Cascade.AllDeleteOrphan() 的映射,我们应该会删除 Parent 也会删除 Children - 否需要做更多,然后删除。只是...... NHibernate并不关心在内存中清除该集合(app server / application)

如果您正在寻找长而稳定的固体解决方案,我强烈建议:

  

拆分READ和WRITE操作

我们(如Web API)的当前框架正在帮助我们朝这个方向发展。我们应该创建一组操作:

  • PUT,POST,DELETE ...处理客户端数据修改请求
  • GET ...按ID或按条件检索数据Find()

每个操作都应该有自己的会话,自己的交易,并且应该代表工作单元。全有或全无。操作成功并且所有操作都是持久的,或者不是(回滚)

这将有助于我们的应用程序成功并在更长/更长的时间内成长。我们分手了。我们关心

1)删除,更新或插入(或者更多的一些根实体,可以看到更多here。 2)我们做READ操作 - 只期望SELECT操作,因此使用最新数据。另请检查this, including comments

虽然这可能有点超出范围,但这个引用形式9.8. Exception handling doc也是线索:

  

...如果ISession抛出异常,你应立即回滚事务,调用ISession.Close()并丢弃ISession实例。某些ISession方法不会离开会议处于一致状态......

我想证明,操作 (会话,交易)应该只有一个目标(WRITE,READ)并且<强>尽可能短 ......