23 Stimmen

fließend nhibernate HasOne WithForeignKey funktioniert nicht

Wenn ich eine Aufgabenklasse lade, ist die Dokumenteigenschaft immer null, obwohl Daten in der Datenbank vorhanden sind.

Aufgabenklasse:

public class Task
{
    public virtual Document Document { get; set; }

Überschreibung der Aufgabenabbildung für AutoPersistenceModel:

public void Override(AutoMap<Task> mapping)
{
    mapping.HasOne(x => x.Document)
        .WithForeignKey("Task_Id");

Wie Sie Form sehen können, was NHProf sagt, wird ausgeführt, die Join-Bedingung ist falsch, die WithForeignKey doesnt scheinen Wirkung zu nehmen. In der Tat kann ich jede Zeichenfolge in den obigen Code schreiben und es macht keinen Unterschied.

FROM   [Task] this_
    left outer join [Document] document2_
    on this_.Id = document2_.Id

So sollte es sein:

FROM   [Task] this_
    left outer join [Document] document2_
    on this_.Id = document2_.Task_Id

Wenn ich die Daten in der Datenbank hacke, so dass die IDs übereinstimmen, werden die Daten geladen, aber offensichtlich ist dies nicht korrekt - aber zumindest beweist es, dass es Daten lädt.

Bearbeiten: Stöbern in der fluent nhib Quelle zu finden, die XML produziert diese:

<one-to-one foreign-key="Task_Id" cascade="all" name="Document" class="MyProject.Document, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 

Bearbeiten: Hier ist das Schema:

CREATE TABLE [dbo].[Document](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Task_Id] [int] NOT NULL,

CREATE TABLE [dbo].[Task](
[Id] [int] IDENTITY(1,1) NOT NULL,

Hat jemand eine Idee?

Danke

Andrew

94voto

PLN Punkte 1071

Ich bin heute auf das gleiche Problem gestoßen. Ich glaube, der Trick ist, nicht .ForeignKey(...) mit der .HasOne-Zuordnung zu verwenden, sondern stattdessen .PropertyRef(...). Im Folgenden definiere ich eine Eins-zu-eins-Beziehung zwischen einer Organisation (Parent) und ihrem Admin (Child):

HasOne(x => x.Admin).PropertyRef(r => r.Organisation).Cascade.All();

Die Verwaltung hat einen einfachen Verweis auf die Organisation über ihren Fremdschlüssel:

References(x => x.Organisation, "ORAD_FK_ORGANISATION").Not.Nullable();

Wenn eine Organisation abgerufen wird, wird der richtige Verwaltungseintrag geladen und Aktualisierungen und Löschungen werden ordnungsgemäß kaskadiert.

6voto

eulerfx Punkte 35316

Sie sollten verwenden:

Referenzen(x => x.Dokument, "DocumentIdColumnOnTask")

5voto

Chris Shaffer Punkte 31499

Ich denke, das Problem hier ist, dass die "HasOne"-Konvention bedeutet, dass Sie auf die andere Sache zeigen (die standardmäßige relationale Art, "Viele zu Eins"/"Eins zu Eins" zu sagen); Indem Sie eine Task_ID auf das Dokument setzen, ist die eigentliche Beziehung ein HasMany, aber Sie haben eine Art implizites Verständnis, dass es nur ein Dokument pro Aufgabe geben wird.

Sorry - ich weiß nicht, wie man dies beheben, aber ich werde daran interessiert sein, zu sehen, was die Lösung ist (Ich benutze nicht NHibernate oder Fluent NHibernate, aber ich habe es in der Zukunft zu verwenden erforscht). Eine Lösung (von jemandem, der nur wenig Ahnung hat) wäre, Documents zu einer Auflistung für Task zu machen und dann eine Document-Eigenschaft bereitzustellen, die das erste Dokument in der Auflistung zurückgibt (mit einer Schnittstelle, die die Documents-Eigenschaft ausblendet, damit niemand denkt, er könne neue Elemente hinzufügen).

Wenn man sich die Dokumentation ansieht und die Antwort von eulerfx berücksichtigt, könnte der Ansatz in etwa so aussehen:

References(x => x.Document)
    .TheColumnNameIs("ID")
    .PropertyRef(d => d.Task_ID);

EDIT: Nur damit diese Antwort die richtige Lösung enthält: Der richtige Weg ist, das Datenbankschema zu aktualisieren, damit es der Absicht des Codes entspricht. Das bedeutet, dass der Tabelle Task eine DocumentID hinzugefügt wird, so dass eine Many-To-One-Beziehung zwischen Task und Document besteht. Wenn Schemaänderungen nicht möglich wären, wäre References() die richtige Lösung.

2voto

tommy Punkte 41

Ich habe diese Lösung ausprobiert:

nur im Dokument:

mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();

0voto

Andrew Bullock Punkte 35376

Wie eulerfx anmerkte,

die Tabellenstruktur zeigt an, dass es möglicherweise mehrere Dokumente für eine Aufgabe gibt

und Chris erklärte:

Indem Sie dem Dokument eine Task_ID zuweisen, ist die eigentliche Beziehung eine HasMany-Beziehung, aber Sie haben eine Art implizites Verständnis, dass es nur ein Dokument pro Task geben wird.

Das ist natürlich richtig, also habe ich es umgekehrt, damit Task eine löschbare Document_Id hat.

Vielen Dank an Sie beide für Ihre Hilfe!

Ich warf eine Münze für die akzeptierte Antwort, wenn ich beides ankreuzen könnte, würde ich es tun!

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