Подтвердить что ты не робот

Свободный nhibernate HasOne WithForeignKey не работает

Всякий раз, когда я загружаю класс Task, свойство Document всегда равно null, несмотря на наличие данных в db.

Класс задачи:

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

Завершение сопоставления задач для AutoPersistenceModel:

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

Как вы видите, как работает NHProf, условие соединения неверно, функция WithForeignKey, похоже, не вступает в силу. Фактически, я могу написать любую строку в приведенном выше коде, и это не имеет значения.

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

Это должно быть:

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

Если я взломаю данные в db, чтобы идентификаторы совпадали, тогда данные загружаются, но, очевидно, это неверно - но, по крайней мере, он доказывает, что он загружает данные.

Изменить: рыться в свободном источнике nhib, чтобы найти XML, производит это:

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

Изменить: 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,

У кого-нибудь есть идеи?

Спасибо

Эндрю

4b9b3361

Ответ 1

Я думаю, что проблема здесь в том, что соглашение "HasOne" означает, что вы указываете на другое (стандартный реляционный способ сказать "много в один" / "один к одному" ); Поместив Task_ID в документ, фактическое отношение является HasMany, но у вас есть какое-то неявное понимание того, что на одну задачу будет только один документ.

Извините - я не знаю, как это исправить, но мне будет интересно узнать, что такое решение (я не использую NHibernate или Fluent NHibernate, но я изучал его для использования в будущем). Решение (от кого-то с очень маленькой идеей) заключалось бы в том, чтобы сделать документы коллекцией в Task, а затем предоставить свойство Document, которое возвращает первый в коллекции (используя интерфейс, который скрывает свойство Documents, поэтому никто не может подумать, что он может добавить новые предметы к нему).

Просматривая документацию и рассматривая ответ eulerfx, возможно, подход будет примерно таким:

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

РЕДАКТИРОВАТЬ: Только так у этого ответа есть соответствующее решение: правильный путь - обновить схему базы данных в соответствии с намерением кода. Это означает добавление DocumentID в таблицу Task, так что между Task и Document существует взаимосвязь Many-To-One. Если изменения схемы не были возможны, ссылка() была бы соответствующим разрешением.

Ответ 2

Сегодня я столкнулся с тем же вопросом. Я считаю, что трюк не использовать .ForeignKey(...) с отображением .HasOne, но вместо этого использовать .PropertyRef(...). Ниже описано, как я определяю отношения "один-к-одному" между организацией (родителем) и ее администратором (дочерним):

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

Администратор имеет простую ссылку на организацию, используя свой внешний ключ:

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

При получении Организации это загрузит правильную запись администратора и правильно каскадирует обновления и удаляет.

Ответ 3

Вы должны использовать:

Ссылки (x = > x.Document, "DocumentIdColumnOnTask" )

Ответ 4

Я пробовал это решение:

только в документе:

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

Ответ 5

Как указывал eulerfx,

структура таблицы указывает, что, возможно, могут быть запущены документы для задачи

и Крис заявил:

Поместив Task_ID в документ, фактическое отношение является HasMany, но у вас есть какое-то неявное понимание того, что на одну задачу будет только один документ.

Это, конечно, правильно, поэтому я отменил его, так что задача имеет нулевую Document_Id.

Спасибо вам обоим за помощь!

Я щелкнул монеткой для принятого ответа, если бы я мог пометить оба, я бы!

Ответ 6

Я боролся с той же проблемой One One и, наконец, обнаружил, что это сработало:

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