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

NHibernate delete child from parent collection with delete cascade

我有两个简单的实体,名为国家和城市。

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服务器和城市有一个外键到国家级联删除。

我正在使用 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 所做的那样)

我发现让它工作的唯一方法是刷新会话(清除、退出...)

使用这种映射,最简单的工作方法是从国家中删除城市 collection 并保存国家。有了级联,城市就会被删除,collection变成你想要的状态

手动删除 collection 项不是解决方案。它实际上破坏了 cascading 特性。

如果我们确实有映射 Cascade.AllDeleteOrphan(),我们应该期望删除 Parent 会删除Children - 无需执行更多操作,然后删除 Parent。只是... NHibernate 不关心清除内存中的 collection (app server/application)

如果您正在寻找长期、稳定、可靠的解决方案,我强烈建议:

Split READ and WRITE operations

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

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

这些操作中的每一个都应该有自己的 session、自己的 事务,并且应该代表 工作单元。全有或全无。要么操作成功全部持久化,要么不成功(rollback)

这将有助于我们的应用程序在 longer/long 运行 中取得成功并不断发展壮大。我们分开。我们关心

1) DELETE、UPDATE 或 INSERT (或更多围绕某个根实体,可以看到更多 here。 2) 我们进行 READ 操作——只期望 SELECT 操作,因此使用 up-to-date 数据。还要检查 this, including comments

虽然这可能有点超出范围,但这个引用表格 9.8. Exception handling 文档也是线索:

...If the ISession throws an exception you should immediately rollback the transaction, call ISession.Close() and discard the ISession instance. Certain methods of ISession will not leave the session in a consistent state...

我想证明 operation (session, transaction) 应该只有一个目标 (WRITE, READ) 尽可能短...