Frage

Ich habe eine viele-zu-eins-Beziehung zwischen Objekten Product und Supplier. Ich muss in der Lage Supplier zu löschen, ohne die Products zu löschen, die zu ihm gehören.

Hier ist eine vereinfachte Version der Klassen:

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; }
}

Ich verwende FluentNHibernate, aber hier sind die Zuordnungen es erzeugt:

<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" />

Dies erzeugt einen Fremdschlüssel auf dem Tisch Produkte, so dass, wenn ich eine gerade löscht auf einem Anbieter zu tun, ich versuche, einen Fremdschlüssel Fehler. Ich habe versucht, Kaskade ‚all‘, in der Hoffnung, zu ändern, dass es vielleicht nur die Beziehung löschen, aber es gelöscht alle Produkte und ihre anderen zugehörigen Objekte.

Der einzige Weg, ich sehe dieses Recht jetzt zu lösen, ist es, die Produkte Sammlung von Lieferanten iterieren und die Lieferanten-Eigenschaft auf null gesetzt. Gibt es eine Weise, die ich dieses Verhalten durch die Zuordnung erreichen kann?

War es hilfreich?

Lösung

Die Abbildungseigenschaften werden erst wirksam, wenn das Unternehmen tatsächlich geladen wird, und wenn Sie abfragen nicht durch HQL. wenn Sie als Beispiel Cascade=ALL angeben, wenn Sie einen Lieferanten mit der Abfrage "delete from Supplier where id=:id" löschen, werden Sie wahrscheinlich das gleiche FK Constraint Scheitern, weil die hql löst keine (programmatische) Kaskaden.

Es scheint, dass die Produkte die besitzende Seite der Beziehung sind, was gut ist. Ich glaube, Sie haben zwei Möglichkeiten:

  • Code einige Verfahren auf den Lieferanten über alle Produkte zu durchlaufen und das Produkt des Lieferanten auf null gesetzt, und diese Methode verwenden, bevor Sie Lieferanten Löschen
  • Vor der Ausstellung ein Lieferant löschen, stellen Sie sicher, dass Ihre DAO das Produkt des Lieferanten setzt auf null

Beispiel:

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

Andere Tipps

dies nicht tun.

Sie haben eine implizite oder explizite Behauptung in Ihrem Modell, dass alle Produkte einen Lieferanten haben. Der Fremdschlüssel ist es, diese Bedingung zu erzwingen. Entfernen des Lieferanten, während die Produkte halten verletzt Ihr Modell und wird wahrscheinlich viel von Ihrem Code verursacht, was auf beruht dies immer der Fall sein, zum Scheitern verurteilt.

Das einzige, was Sie tun können, haben Sie bereits entdeckt: für jedes Produkt, das diesen Lieferanten hat, können Sie das Produkt des Lieferanten null gesetzt. Dies wird nicht Ihre Bedingung verletzen, aber es ist die gleiche wie zu sagen: „Wir wissen nicht, wer der Lieferant für dieses Produkt ist“ und können ein Code-Fehler verursachen.

Warum wollen Sie das tun?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top