質問

オブジェクト Product Supplier の間に多対1の関係があります。 Supplier に属する Product を削除せずに Supplier を削除できるようにする必要があります。

クラスの簡略版は次のとおりです。

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のProductsコレクションを反復処理し、Supplierプロパティをnullに設定することです。マッピングを通じてこの動作を実現する方法はありますか?

役に立ちましたか?

解決

マッピングプロパティは、エンティティが実際にロードされ、HQLを介してクエリを実行していない場合にのみ有効になります。例として、 Cascade = ALL を指定した場合、クエリ&quot; delete from Supplier from id =:id&quot; でサプライヤーを削除すると、おそらくhqlは(プログラム的な)カスケードをトリガーしないため、同じFK制約エラーが発生します。

製品は関係の所有側であると思われますが、これは良いことです。次の2つの選択肢があると思います。

  • すべての製品を反復処理し、製品のサプライヤをnullに設定するメソッドをサプライヤでコーディングし、サプライヤを削除する前にこのメソッドを使用します
  • サプライヤ削除を発行する前に、DAOが製品のサプライヤをnullに設定していることを確認してください

例:

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

他のヒント

これをしないでください。

すべての製品にサプライヤーがあるというモデルの暗黙的または明示的な主張がある。この条件を強制するために外部キーがあります。製品を保持したままサプライヤを削除すると、モデルに違反し、おそらくこれが常に真であることに依存するコードの多くが失敗する可能性があります。

できることの1つは、すでに発見したことです。このサプライヤを持つすべての製品について、製品のサプライヤをnullに設定できます。これはあなたの条件に違反しませんが、「この製品の供給者が誰なのかわからない」と言うのと同じです。コードエラーが発生する可能性があります。

なぜこれを行うのですか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top