NHibernate多对一关系仅删除父级

时间:2009-04-29 10:13:32

标签: nhibernate nhibernate-mapping many-to-one

我在对象ProductSupplier之间存在多对一关系。我需要能够删除Supplier而不删除属于它的Product

以下是类的简化版本:

public class Supplier {
    public virtual IList<Product> Products { get; protected set; }
}

public class Product {
    // Product belongs to a Category but Supplier is optional
    public virtual Supplier Supplier { get; set; }
    public virtual Category Category { get; set; }
}

我正在使用FluentNHibernate,但这是它产生的映射:

<bag name="Products" cascade="save-update" inverse="true">
      <key column="SupplierID" />
      <one-to-many class="Me.Product, Me, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

<many-to-one name="Supplier" column="SupplierID" />

这会在Products表上创建一个外键,因此当我尝试在Supplier上进行直接删除时,会出现外键约束错误。我尝试将级联更改为'all',希望它可能只删除关系,但它删除了所有产品及其他相关对象。

我现在能够看到解决此问题的唯一方法是迭代Supplier的Products集合并将Supplier属性设置为null。有没有办法通过映射实现这种行为?

2 个答案:

答案 0 :(得分:2)

映射属性仅在实际加载实体时以及未通过HQL查询时生效。例如,如果指定Cascade=ALL,如果删除带有查询"delete from Supplier where id=:id"的供应商,则可能会遇到相同的FK约束失败,因为hql不会触发(编程)级联。 / p>

似乎产品是关系的拥有方,这很好。我认为你有两个选择:

  • 在供应商处编写一些方法来迭代所有产品并将产品供应商设置为null,并在删除任何供应商之前使用此方法
  • 在发布供应商删除之前,请确保您的DAO将产品的供应商设置为空

示例:

public int Delete(Supplier s) {
    return Session.CreateQuery("udpate Product set Supplier = null where Supplier = :supplier")
        .SetParameter("supplier", s)
        .ExecuteUpdate();
}

答案 1 :(得分:0)

请勿这样做。

您的模型中有一个隐含或显式断言,所有产品都有供应商。外键是为了强制执行这种情况。在保留产品的同时删除供应商会违反您的模型,并可能导致您的大部分代码(依赖于此始终如此)失败。

您可以做的一件事是,您已经发现:对于拥有此供应商的每个产品,您都可以将产品供应商设置为空。这不会违反您的条件,但与“我们不知道该产品的供应商是谁”相同并且可能导致代码失败。

你为什么要这样做?