fluent NHibernate HasOne WithForeignKey nie działa

Za każdym razem, gdy Ładuję klasę Zadań, właściwość Document jest zawsze null, mimo że w db są dane.

Klasa zadania:

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

Task Mapping override for AutoPersistenceModel:

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

Jak widać w formularzu co nhprof mówi jest uruchamiany, warunek join jest zły, WithForeignKey nie wydaje się działać. W rzeczywistości mogę napisać dowolny ciąg w powyższym kodzie i to nie robi różnicy.

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

Powinno być:

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

If i zhakuj dane w db tak, aby ids pasowały, a następnie dane są ładowane, ale oczywiście jest to nieprawidłowe - ale przynajmniej dowodzi, że ładuje dane.

Edit: grzebanie w płynnym źródle nhib w celu znalezienia XML powoduje to:

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

Edit: heres the 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,
Ktoś ma jakieś pomysły?

Dzięki

Andrzej

Author: Andrew Bullock, 2009-03-13

6 answers

Myślę, że problem polega na tym, że konwencja "HasOne" oznacza, że wskazujesz na inną rzecz( standardowy relacyjny sposób, aby powiedzieć "wiele do jednego" / "jeden do jednego"); umieszczając identyfikator Task_ID na dokumencie, rzeczywisty związek jest HasMany, ale masz jakieś ukryte zrozumienie, że będzie tylko jeden dokument na zadanie.

Sorry-Nie wiem jak to naprawić, ale zainteresuje mnie jakie jest rozwiązanie (nie używam NHibernate ani Fluent NHibernate, ale badałem go do wykorzystania w przyszłości). Rozwiązaniem (od kogoś z bardzo małym pomysłem) byłoby stworzenie kolekcji dokumentów na zadaniu, a następnie dostarczenie Właściwości dokumentu, która zwróci pierwszą z kolekcji (używając interfejsu, który ukrywa właściwość dokumenty, aby nikt nie myślał, że może dodać do niej nowe elementy).

Przeglądając dokumentację i biorąc pod uwagę odpowiedź eulerfx, być może podejście byłoby coś w stylu:

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

EDIT: tak to odpowiedź ma odpowiednie rozwiązanie: prawidłową ścieżką jest aktualizacja schematu bazy danych, aby pasował do intencji kodu. Oznacza to dodanie DocumentID do tabeli zadań, więc istnieje relacja wiele do jednego między zadaniem a dokumentem. Gdyby zmiany w schemacie nie były możliwe, Reference() byłoby odpowiednią rozdzielczością.

 5
Author: Chris Shaffer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-13 17:57:53

Natknąłem się dziś na ten sam problem. Myślę, że sztuczka polega na tym, żeby jej nie używać .ForeignKey(...) z .Mapowanie HasOne, ale do wykorzystania .PropertyRef(...) zamiast. Oto, jak definiuję relację jeden do jednego między organizacją (rodzicem) a jej administratorem (dzieckiem): {]}

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

Administrator ma proste odniesienie do organizacji za pomocą klucza obcego:

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

Podczas pobierania organizacji ładuje się prawidłowy rekord administratora i odpowiednio kaskaduje aktualizacje i usuwa.

 94
Author: PLN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-05 11:42:42

Powinieneś użyć:

References (x => X.Document, "DocumentIdColumnOnTask")

 6
Author: eulerfx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-13 17:10:27

Próbowałem tego rozwiązania:

Tylko w dokumencie:

mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();
 2
Author: tommy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-27 11:11:16

Jak zauważył eulerfx,

Struktura tabeli wskazuje, że może być wiele dokumentów dla zadania

A Chris stwierdził:

Poprzez umieszczenie Task_ID na dokumencie rzeczywisty związek jest HasMany, ale masz pewien rodzaj ukrytego zrozumienia, że będzie tylko jeden dokument na zadanie.

Jest to oczywiście poprawne, więc odwróciłem to, więc Task ma nullable Document_Id.

Dzięki wam obojgu za was pomocy!

Rzuciłem monetą za zaakceptowaną odpowiedź, gdybym mógł zaznaczyć obie, zrobiłbym to!

 0
Author: Andrew Bullock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-13 17:46:24

Zmagałem się z tym samym problemem i w końcu okazało się, że to działa:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        Id(x => x.Id);
        HasOne(s => s.Child).Cascade.All();
    }
}

 public class ChildMap : ClassMap<Model.Child>
{
    public ChildMap()
    {
        Id(x => x.Id);
        HasOne(s => s.Parent).Constrained().ForeignKey();           
    }
}
 0
Author: Sean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-30 10:33:39