【问题标题】:NHibernate delete child from parent collection with delete cascadeNHibernate 使用删除级联从父集合中删除子级
【发布时间】:2015-05-16 16:07:38
【问题描述】:

我有两个简单的实体,分别命名为 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,并且 City 有一个 Country 的外键,具有级联删除功能。

我正在使用 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 一样)

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

【问题讨论】:

  • 这是不可能的,也不应该是。删除实体不会改变内存中的内容。在这种情况下,您有责任清除收藏。

标签: c# nhibernate fluent-nhibernate


【解决方案1】:

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

如果我们确实有映射 Cascade.AllDeleteOrphan(),我们应该期望删除 Parent 也会删除 Children - 不需要做更多然后删除 Parent。只是... NHibernate 不关心清除内存中的集合(应用服务器/应用程序)

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

拆分读写操作

我们目前拥有的框架(如 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 的某些方法不会使会话保持一致状态...

我想证明,操作 (session, transaction)应该只有一个目标(WRI​​TE, READ)并且是尽可能短...

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这不是真正的问题。当我删除国家/地区时,城市也被删除,但仍保留在国家/地区集合中。在 EF6 中,当您执行相同操作时,所有对象都保持已删除状态,并且城市将从父集合中删除。这是我所期望的行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多