2 Stimmen

Warum kann ich nicht auf untergeordnete Entitäten mit einem Teil des zusammengesetzten Schlüssels der übergeordneten Entität verweisen?

Ich versuche, einige untergeordnete Entitäten mit einem Teil des zusammengesetzten Schlüssels der Eltern zu referenzieren, aber nicht mit dem gesamten Schlüssel, warum geht das nicht? Dies geschieht, wenn ich die folgende Zuordnung anstelle der kommentierten Zuordnung verwende.

Ich erhalte den folgenden Fehler

Fremdschlüssel in Tabelle VolatileEventContent muss dieselbe Anzahl von Spalten haben wie der referenzierte Primärschlüssel in der Tabelle LocationSearchView

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
  <class name="LocationSearchView" table="LocationSearchView">

    <composite-id>
      <key-property name="LocationId" type="Int32"></key-property>
      <key-property name="ContentProviderId" type="Int32"></key-property>
      <key-property name="CategoryId" type="Int32"></key-property>
    </composite-id>

    <property name="CompanyName" type="String" not-null="true" update="false" insert="false"/>
    <property name="Description" type="String" not-null="true" update="false" insert="false"/>
    <property name="CategoryId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="ContentProviderId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="LocationId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="Latitude" type="Double"  update="false" insert="false" />
    <property name="Longitude" type="Double"  update="false" insert="false" />

    <bag name="Events" table="VolatileEventContent" where="DeactivatedOn IS NULL" order-by="StartDate DESC" lazy="false" cascade="none">
      <key>
        <column name="LocationId"></column>
        <column name="ContentProviderId"></column>
        <!--<column name="LocationId"></column>
        <column name="ContentProviderId"></column>
        <column name="CategoryId"></column>-->
      </key>
      <one-to-many class="Event" column="VolatileEventContentId"></one-to-many>
    </bag>

  </class>
</hibernate-mapping>

Und VolatileEventContent-Zuordnungsdatei

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
  <class name="Event" table="VolatileEventContent" select-before-update="false" optimistic-lock="none">
    <composite-id>
      <key-property name="LocationId" type="Int32"></key-property>
      <key-property name="ContentProviderId" type="Int32"></key-property>
    </composite-id>

    <property name="Description" type="String" not-null="true" update="false" insert="false"/>

    <property name="StartDate" type="DateTime" not-null="true" update="false" insert="false" />
    <property name="EndDate" type="DateTime" not-null="true" update="false" insert="false" />

    <property name="CreatedOn" type="DateTime" not-null="true" update="false" insert="false" />
    <property name="ModifiedOn" type="DateTime" not-null="false" update="false" insert="false" />

    <many-to-one name="Location" class="Location" column="LocationId" />

    <bag name="Artistes" table="EventArtiste" lazy="false" cascade="none">
      <key name="VolatileEventContentId" />
      <many-to-many class="Artiste" column="ArtisteId" ></many-to-many>
    </bag>
  </class>
</hibernate-mapping>

2voto

Daniel Schilling Punkte 4800

Der Fehler ist korrekt. Ich vermute, dass Sie Folgendes verwenden SchemaExport um Ihre Tabellen auf der Grundlage der NHibernate-Mappings zu generieren, da der Fehler, den Sie erhalten, sich so anhört, als würde er bei der Erstellung Ihrer Tabellen und Fremdschlüssel auftreten. SchemaExport würde ähnliche Tabellen wie die folgenden ergeben (bitte beachten Sie die im Code verstreuten Erläuterungen):

CREATE TABLE LocationSearchView (
    LocationId int NOT NULL,
    ContentProviderId int NOT NULL,
    CategoryId int NOT NULL,

    /* ...other columns... */

    /* Note: Generated from LocationSearchView's "composite-id" element.  */
    PRIMARY KEY (LocationId, ContentProviderId, CategoryId)
);

/* Note: Table for the "Event" class. */
CREATE TABLE VolatileEventContent (
    LocationId int NOT NULL,
    ContentProviderId int NOT NULL,

    /* ...other columns... */

    /* Note: Generated from Event's "composite-id" element. */
    PRIMARY KEY (LocationId, ContentProviderId),
    /* Note: Generated from the "key" element of LocationSearchView's Events bag. */
    FOREIGN KEY (LocationId, ContentProviderId) REFERENCES LocationSearchView (LocationId, ContentProviderId)
);

... daher der Fehler. Ein Fremdschlüssel muss auf einen vollständigen Primär- oder eindeutigen Schlüssel verweisen - nicht nur auf einen Teil eines Primärschlüssels. Der gesamte Schlüssel besteht aus 3 Spalten, nicht aus 2. Warum sollte NHibernate diese Spalten für den Fremdschlüssel verwenden? Wegen der <key> Element von LocationSearchView 's Events Tasche. <key> gibt an, welche Spalten aus der Datei Kind zurück zum Elternteil .

Betrachten wir nun, was passieren könnte, wenn Sie (oder NHibernate) versuchen, aus diesen Tabellen auszuwählen. Nehmen wir die folgenden Daten an:

TABLE LocationSearchView
LocationId ContentProviderId CategoryId
========== ================= ==========
1          3                 5
1          3                 6
1          4                 5
1          4                 6
2          3                 5
2          3                 6
2          4                 5
2          4                 6
    TABLE VolatileEventContent
LocationId ContentProviderId
========== =================
1          3
1          4
2          3
2          4

Es ist nicht möglich, dass "einer" LocationSearchView "viele" zu haben Event s. Vielmehr sollte es umgekehrt sein. Bei diesen Tabellen gibt es eigentlich eine eins-zu-viele-Beziehung von Event a LocationSearchView .

Ich weiß nicht, was die richtige Lösung für dieses Problem ist, weil ich nicht weiß, was Sie zu erreichen versuchen, aber ich hoffe, dass dies hilft, das Problem zu erhellen.

0voto

Thierry Punkte 5010

Ich habe nhibernate nie benutzt, aber ich vermute, dass das Mapping dem von hibernate sehr ähnlich ist.

Wenn Sie nicht möchten, dass Ihre one-to-many (LocationSearchView zu vielen VolatileEventContent) Assoziation die LocationSearchView id verwendet, müssen Sie auf dem Schlüsselelement der Tasche das Attribut "property-ref" definieren, das die stattdessen zu verwendende Eigenschaft definiert:

<bag name="Events" table="VolatileEventContent" ...>
  <key property-ref="partialId">
    <column name="LocationId"></column>
    <column name="ContentProviderId"></column>
  </key>
  <one-to-many class="Event" column="VolatileEventContentId"></one-to-many>
</bag>

(das Spaltenattribut ist für ein One-to-many-Tag gültig ?)

Nun müssen Sie eine Eigenschaft mit diesem Namen definieren, etwa so:

<properties name="partialId" insert="false" update="false">
  <property name="LocationId" type="Int32" update="false" insert="false"/>
  <property name="ContentProviderId" type="Int32" update="false" insert="false"/>
</properties>

Sie haben bereits LocationId und ContentProviderId definiert. Verschieben Sie diese beiden Eigenschaften einfach innerhalb des Elements properties.

0voto

Jaguar Punkte 5900

Zunächst einmal haben Sie einen Fehler in Ihrer Zuordnung für " LocationSearchView " Sie definieren die CategoryId Spalte sowohl als Eigenschaft als auch als Teil der Composite-id. Dies ist falsch, wird aber leider bei der Erstellung des Mappings nicht berücksichtigt und wird normalerweise bei der Abfrage des Objekts sichtbar. check IndexOutOfRangeException Tief in den Eingeweiden von NHibernate

Das könnte den Mapping-Parser verwirren. Und ich sage verwirrend weil Sie sich bei Ihren beiden Zuordnungen auf Reflexion und Konvention stützen, die eine diszipliniertere Programmiermethodik voraussetzen:

  1. Sie definieren nicht explizit die class Attribut des many-to-one y bag Elemente, sondern man erwartet von NHibernate, dass es den Klassentyp aus der Klassendefinition selbst erkennt. Wenn Sie zufällig in der Klasse LocationSearchView die folgenden IList<LocationSearchView> Events {get;set;} nhibernate würde erwarten, dass die LocationSearchView Klasse für die definierte bag und benötigen daher die 3 Spalten zur Abbildung der Sammlung
  2. Sie haben dieselben Eigenschaftsnamen für die Spaltennamen, was die Entwicklung erleichtert (eigentlich erleichtert es nur die Erstellung von Zuordnungen, die Sie ohnehin nur ein- oder zweimal vornehmen), aber im Falle von Fehlern oder Änderungen ist es schwieriger zu erkennen, was falsch gelaufen ist.

Machen Sie also Ihre Mappings reichhaltiger und beseitigen Sie den Fehler, den ich mit CategoryId Geben Sie auch die Klassen in Ihrem Beitrag an!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X