【问题标题】:could not delete collection : [NHibernate.Exceptions.GenericADOException]无法删除集合:[NHibernate.Exceptions.GenericADOException]
【发布时间】:2015-05-05 06:25:50
【问题描述】:

我有两个表,tableA 和 tableB。

tableA 有列:tabAId、col2、col3 (tabAId primaryKey 和 Identity 列。)

tableB 有列:tabAId,名称(tabAId 不为空)

我已经在tableA的hbm文件中创建了Bag,用来维护关系。

<bag name="tableB" lazy="true" inverse="false"
                    batch-size="25" cascade="all-delete-orphan">
  <key column="tabAId" />
  <one-to-many class="tableB" />
</bag>

当我尝试更新 tableA 中的记录时,它会抛出异常,因为我在 tableA 实例中有子列表。

[NHibernate.Exceptions.GenericADOException] = {"无法删除集合:[MIHR.Entities.tableA.tableB#21][SQL: UPDATE dbo.tableB SET tabAId = null WHERE tabAId = @p0]"}

InnerException = {"无法将 NULL 值插入列 'tabAId',表 'SA_MIHR_DEV.dbo.tableB'; 列不允许空值。 UPDATE 失败。\r\n语句已终止。"}

【问题讨论】:

    标签: c# hibernate nhibernate hbm


    【解决方案1】:

    解决这个问题的方法只有两种。

    1) 不要使用inverse="false"

    <bag name="tableB" lazy="true" inverse="true" // instead of false
                        batch-size="25" cascade="all-delete-orphan">
      <key column="tabAId" />
      <one-to-many class="tableB" />
    </bag>
    

    这个设置(inverse="true") 将指示NHibernate 直接从数据库中删除一个item

    虽然使用inverse="false" 通常会导致:

    • UPDATE (with null) == 从集合中删除的行为
    • 删除项目 == 级联行为

    2) 使引用列可以为空

    这意味着,我们可以让 NHibernate 去做 UPDATE 和 DELETE。因为列现在可以为空。

    这里只有两种解决方法。

    我的偏好是:inverse="true"

    为了与 inverse="true" 正常工作,我们总是必须在 C# 中分配关系的双方。这是 Add()、INSERT 操作必须的:

    Parent parent = new Parent();
    Child child = new Child
    {
        ...
        Parent = parent,
    };
    // unless initialized in the Parent type, we can do it here
    parent.Children = parent.Children ?? new List<Child>();
    parent.Children.Add(child);
    
    // now just parent could be saved
    // and NHibernate will do all the cascade as expected
    // and because of inverse mapping - the most effective way
    session.Save(parent);
    

    如我们所见,我们已明确指定 - 双方的关系。这是从 NHibernate 逆映射中获利的必要条件。这也是一个很好的做法,因为稍后,当我们从我们期望的数据库中加载数据时,NHibernate 会为我们设置这些

    【讨论】:

    • 如果我设置 Inverse="true" 那么它不会在子表中插入新生成的标识列值,同时在父表中插入新记录。
    • 科勒:请告诉我该怎么做,我什么时候设置inversr="true"
    • 现在你应该看到了......我更新了我的答案。当然,您的子实体必须引用父实体。检查此stackoverflow.com/a/30005490/1679310 了解所有详细信息
    • 科勒:让我按照你的方式来吧。
    • Kohler : 1- 当您尝试在列表中添加子项时,它会抛出异常,因为您还没有初始化子对象。 2- 在 child 中添加 Parent 对象,它将创建循环引用。
    猜你喜欢
    • 2014-08-13
    • 2012-11-19
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2019-04-10
    • 2017-05-08
    相关资源
    最近更新 更多