Beste Weg, um Modell-Viele-Zu-Eins-Beziehungen in NHibernate Beim Umgang Mit Legacy-DB?

StackOverflow https://stackoverflow.com/questions/10915

  •  08-06-2019
  •  | 
  •  

Frage

Warnung - ich bin sehr neu in NHibernate.Ich weiß, diese Frage scheint einfach zu sein - und ich bin sicher, es gibt eine einfache Antwort, aber ich habe Spinnen meine Räder für einige Zeit auf diese ein.Ich bin den Umgang mit legacy-db, was wirklich nicht verändert werden kann strukturell.Ich habe eine ausführliche Tabelle, die Zahlung Pläne wurden vom Kunden akzeptiert.Jede Zahlung plan hat eine ID, die links zurück zu einer Referenz Tabelle, um den plan der Bedingungen, etc.In meiner Objekt-Modell, ich habe eine AcceptedPlan Klasse, und einen Plan.Klasse.Ursprünglich habe ich eine viele-zu-eins-Beziehung aus der detail-Tabelle zurück auf den ref-Tisch zu modellieren, diese Beziehung in NHibernate.Ich habe auch eine eins-zu-viele-Beziehung in die entgegengesetzte Richtung von der Plan-Klasse über die AcceptedPlan Klasse.Das war schön, während ich war einfach Lesen von Daten.Ich konnte mein Plan-Objekt, das eine Eigenschaft meiner AcceptedPlan Klasse Lesen den plan details.Mein problem entstand, als ich hatte zu Beginn das einfügen neuer Zeilen in die Tabelle.Aus meiner Lektüre scheint es der einzige Weg, um erstellen Sie ein neues untergeordnetes Objekt hinzufügen und es auf das parent-Objekt und speichern Sie die Sitzung.Aber ich will nicht zu haben, um erstellen Sie einen neuen übergeordneten Plan-Objekt jedes mal, wenn ich will erstellen Sie ein neues detail record.Dies scheint, wie einen unnötigen overhead.Weiß jemand, ob ich dabei bin, über dieses in die falsche Richtung?

War es hilfreich?

Lösung

Ich würde Steuern Weg von Kind-Objekt mit deren logische übergeordneten, kann es sehr chaotisch und sehr rekursive ziemlich schnell, wenn Sie das tun.Ich würde schauen, wie Sie sind beabsichtigen, verwenden Sie das domain-Modell, bevor Sie tun, diese Art der Sache.Sie können ganz einfach noch die ID verweist, die in die Tabellen und nur lassen Sie unmapped.

Hier sind zwei Beispiele für Zuordnungen, die bringen könnte, Sie in die richtige Richtung, ich habe die adlib-Tabelle, Namen usw. aber es könnte möglicherweise helfen.Ich würde wahrscheinlich auch vorschlagen, mapping the StatusId auf eine Aufzählung.

Achten Sie auf die Art der Tasche, effectivly Karten die details-Tabelle wird in eine Sammlung.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="CustomerAccountId" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/>
            <generator class="native" />
        </id>

        <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan" table="details">
          <key column="CustomerAccountId" foreign-key="AcceptedOfferFK"/>
          <many-to-many
            class="Namespace.AcceptedOffer, Namespace"
            column="AcceptedOfferFK"
            foreign-key="AcceptedOfferID"
            lazy="false"
           />
        </bag>

  </class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="AcceptedOffer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="AcceptedOfferId" length="4" sql-type="int" not-null="true" unique="true" index="AcceptedOfferPK"/>
            <generator class="native" />
        </id>

        <many-to-one 
          name="Plan"
          class="Namespace.Plan, Namespace"
          lazy="false"
          cascade="save-update"
        >
        <column name="PlanFK" length="4" sql-type="int" not-null="false"/>
        </many-to-one>

        <property name="StatusId" type="Int32">
            <column name="StatusId" length="4" sql-type="int" not-null="true"/>
        </property>

  </class>
</hibernate-mapping>

Andere Tipps

Nicht sehen Ihre Datenbank Diagramm, während ich Schreibe.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="customer_id" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/>
            <generator class="native" />
        </id>

        <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan">
            <key column="accepted_offer_id"/>
            <one-to-many class="Namespace.AcceptedOffer, Namespace"/>
        </bag>

  </class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="Accepted_Offer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="accepted_offer_id" length="4" sql-type="int" not-null="true" unique="true" />
            <generator class="native" />
        </id>

        <many-to-one name="Plan" class="Namespace.Plan, Namespace" lazy="false" cascade="save-update">
            <column name="plan_id" length="4" sql-type="int" not-null="false"/>
        </many-to-one>

  </class>
</hibernate-mapping>

Wahrscheinlich sollte den trick tun (habe ich nur getan, B. Zuordnungen für die Sammlungen, Sie werden müssen hinzufügen andere Eigenschaften).

Der Ansatz, den ich nehmen würde, um dieses Modell ist wie folgt:

Customer-Objekt enthält eine ICollection <PaymentPlan> PaymentPlans das sind die Pläne, die der Kunde akzeptiert hat.

Die PaymentPlan, die der Kunde zugeordnet werden, mit einer Tasche, die Sie verwendet, und die details-Tabelle, um festzustellen, welche Kunden-id zugewiesen, die PaymentPlans.Cascade all-delete-orphan, wenn der Kunde gelöscht wurde, werden sowohl die Einträge aus details und die PaymentPlans, dass der Kunde im Besitz gelöscht werden.

Die PaymentPlan-Objekt enthält eine PlanTerms Objekt vertreten, die die Bedingungen der Zahlung plan.

Die PlanTerms würde zugeordnet werden PaymentPlan mit einer viele-zu-eins-Zuordnung cascading save-update, das würde nur legen Sie einen Verweis auf die relevanten PlanTerms Objekt in der PaymentPlan.

Mit diesem Modell können Sie PlanTerms unabhängig und dann, wenn Sie, fügen Sie eine neue PaymentPlan an einen Kunden, Sie würde erstellen Sie eine neue PaymentPlan Objekt vorbei in die entsprechenden PlanTerms Objekt und fügen Sie es anschließend, um die Sammlung auf dem jeweiligen Kunden.Schließlich würden Sie sparen sich die Kunden und lassen cascade nhibernate die speichern-operation.

Sie würde am Ende mit einem Kunde-Objekt, ein PaymentPlan Objekt und eine PlanTerms Objekt mit dem Kunden (Kunden-Tabelle) besitzen Instanzen von PaymentPlans (die Tabelle), die alle adhear zu bestimmten PlanTerms (der plan Tabelle).

Ich habe einige konkretere Beispiele für die Zuordnung syntax, wenn erforderlich, aber es ist wahrscheinlich am besten, es durch mit Ihrem eigenen Modell und ich habe nicht genug Informationen über die Tabellen der Datenbank zu liefern, keine spezifischen Beispiele.

Ich weiß nicht, ob dies ist möglicherweise, weil meine NHibernate-Erfahrung ist begrenzt, aber könnte Sie erstellen eine BaseDetail Klasse, die gerade die Eigenschaften, die für die Details Sie anzeigen direkt in der Detail-Tabelle.

Dann erstellen Sie eine zweite Klasse, erbt von der BaseDetail-Klasse, die die zusätzlichen Übergeordneten Plan-Objekt, so dass Sie können erstellen eine BaseDetail Klasse, wenn Sie wollen, erstellen Sie einfach eine Zeile Detail und weisen Sie die PlanId, aber wenn Sie brauchen, um füllen Sie eine vollständige Detail-Datensatz mit dem Übergeordneten plan Objekt, das Sie verwenden können, die vererbt Detail-Klasse.

Ich weiß nicht, ob das macht das ganze viel Sinn, aber lassen Sie mich wissen, und ich werde klären, weiter.

Ich denke, das problem, das Sie hier haben, ist, dass Ihre AcceptedOffer Objekt enthält einen Plan-Objekt und dann Ihren Plan-Objekt angezeigt wird, enthalten ein AcceptedOffers Sammlung enthält AcceptedOffer Objekte.Gleiche Sache mit Kunden.Die Tatsache, dass die Objekte ein Kind des jeweils anderen ist, welche Ursachen dein problem, denke ich.

Ebenso, was macht Ihr AcceptedOffer Komplex ist, es hat zwei Aufgaben:es gibt Angebote, die in einem plan, es gibt die Annahme durch den Kunden.Das verstößt gegen das Prinzip der Einzigen Verantwortung.

Sie kann haben zu unterscheiden zwischen einem Angebot, das unter einen Plan und ein Angebot, das angenommen von den Kunden.Also hier ist was ich tun werde:

  1. Erstellen Sie ein separates Angebot-Objekt, das nicht einen Status haben, z.B., es nicht haben ein Kunde und nicht eine status-es hat nur eine OfferId und der Plan es gehört zu seinen Attributen.
  2. Ändern Sie Ihre Plan-Objekt Bietet eine Sammlung (es muss nicht akzeptiert haben, bieten in Ihrem Kontext).
  3. Schließlich ändern Sie Ihre AcceptedOffer Objekt, so dass es enthält ein Angebot, das den Kunden und den Status.Der Kunde bleibt das gleiche.

Ich denke, das wird genug entwirren Sie Ihre NHibernate-mappings und Objekt-speichern Probleme.:)

Ein Tipp, der möglicherweise (oder möglicherweise nicht) hilfreich sein, in NHibernate:Sie können die Zuordnung der Objekte gegen Ansichten, als ob die Aussicht war eine Tabelle.Geben Sie einfach den Namen der Sicht, als Tabelle name;solange alle NICHT-NULL-Felder enthalten sind, in die Ansicht, und die Zuordnung wird es funktionieren.

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