Свободный NHibernate: нарушение внешнего ключа или нулевые значения

Привет, ребята, у меня возникли серьезные проблемы с отображением с использованием свободного nhibernate. Я понимаю, что как на этом сайте, так и во многих других есть МНОГО сообщений, посвященных определенным типам картографии, но пока я не нашел решения, которое решает мою проблему.

Вот что у меня есть:

namespace MyProject.Models.Entites
{
    public class Project
    {
       public virtual Guid Id {get; set;}
       // A load of other properties
       public virtual ProjectCatagory Catagory{get;set;}           
    }
}

а затем карта:

namespace MyProject.DataAccess.ClassMappings
{
    public class ProjectMap : ClassMap<Project>
    {
        public ProjectMap()
        {
            Id(x => x.Id);
            Map(x => x.Title);
            Map(x => x.Description);
            Map(x => x.LastUpdated);
            Map(x => x.ImageData).CustomSqlType("image");
            HasOne(x => x.Catagory);           
        }
    }
}

Итак, как видите, у меня есть проект, который содержит свойство catagory. Я не в восторге от реляционных баз данных, но насколько я могу судить, это отношения «много-один», когда многие проекты могут иметь одну категорию. Нет, проекты не могут относиться более чем к одной категории.

Итак, теперь у нас есть:

namespace MyProject.Models.Entities
{
   public class ProjectCatagory
   {
        public virtual Guid Id { get; set; }
        public virtual String Name { get; set; }
   }
}

и его карта:

public ProjectCatagoryMap()
{
    Id(x => x.Id);
    Map(x => x.Name);
}

Проблема в том, что это не работает! Я сделаю что-то подобное в модульном тесте:

Project myproject = new Project("Project Description");
// set the other properties
myProject.Catagory = new ProjectCatagory(Guid.New(), "Test Catagory");
repository.Save(myProject);

Теперь я попробовал несколько конфигураций сопоставления и базы данных, пытаясь заставить это работать. В настоящее время в таблице базы данных Project есть столбец «Catagory_id» (который я не помещал туда, я предполагаю, что NH добавил его в результате сопоставления), и мне НРАВИТСЯ, что он настроен так, чтобы не допускать нулей. Однако, когда установлен как таковой, я получаю исключения, объясняющие, что я не могу вставлять нулевые значения в таблицу (даже если во время отладки я проверил все свойства объекта Project, и они НЕ равны нулю).

В качестве альтернативы я могу разрешить таблице принимать нули в этот столбец, и она просто сохранит объект Project и полностью проигнорирует свойство Category при сохранении, поэтому при извлечении тесты, чтобы проверить, была ли правильная категория связана с проектом, не удается .

Если я правильно помню, однажды я использовал ProjectMap:

References(x => x.Catagory).Column("Catagory_id").Cascade.All().Not.Nullable();

это изменило исключение с «Невозможно вставить нулевые значения» на нарушение внешнего ключа.

Я подозреваю, что корень всех этих проблем происходит из-за моего непонимания настроенной реляционной базы данных, поскольку у меня есть другие объекты в этом проекте, которые не имеют внешних зависимостей, которые абсолютно нормально работают с NHibernate, что исключает любые проблемы с кодированием, которые я могу вызвать, когда создание репозитория.

Любая помощь очень ценится. Спасибо.


person SomeGuy    schedule 14.06.2010    source источник
comment
Измените заголовок на что-то вроде Fluent NHibernate: Проблема с HasOne, чтобы сделать его более конкретным.   -  person Stefan Steinegger    schedule 14.06.2010


Ответы (3)


Основная проблема здесь - это распространенное неправильное понимание отношения «один-к-одному» в реляционной базе данных и отображения HasOne в Fluent. Термины в отображении являются относительными. (Fluent пытается их немного «украсить», что, ИМО, усугубляет ситуацию. HasOne на самом деле означает: один на один.)

Взгляните на Fluent wiki:

HasOne обычно зарезервирован для особого случая. Как правило, в большинстве ситуаций вы должны использовать отношение «Ссылки» (см.: Я думаю, вы имеете в виду отношение «многие к одному»).

Решение очень простое: просто замените HasOne на Referencesone-to-one на many-to-one в файле сопоставления XML). Вы получаете внешний ключ в базе данных, который ссылается на ProjectCatagory.


Реальное взаимно-однозначное отношение в реляционной базе данных идеально отображается с помощью синхронизации первичного ключа. Когда два объекта используют один и тот же первичный ключ, вы не тратите место на дополнительные внешние ключи, и это гарантирует, что он будет взаимно однозначным.

Чтобы синхронизировать первичный ключ, вам нужно связать один ключ с другими. Как бы то ни было, это работает, здесь это не то, что вам нужно.

person Stefan Steinegger    schedule 14.06.2010
comment
Я понимаю, что HasOne () на самом деле неверен в этих терминах, но, как говорится в нижней части сообщения, я попытался использовать просто References (), и он не работает, говоря, что оператор вставки конфликтует с ограничением внешнего ключа на таблица ProjectCatagory. - person SomeGuy; 14.06.2010

Поигрался со всеми доступными вариантами маппинга. Я нашел ответ похожим на предложенный.

Как и предполагалось, HasOne() был явно неправ, и References(x => x.Catagory) был частью решения. Однако я все еще получал исключения о нарушении внешнего ключа до тех пор, пока:

References(x => x.Catagory).Column("Catagory_id").Cascade.SaveUpdate().Not.Nullable().Not.LazyLoad();

Просто подумал, что id обновит поток, если кто-то еще наткнется на это с аналогичной проблемой, поскольку просто использование References() не сработало.

person SomeGuy    schedule 16.06.2010

Кажется, что класс ProjectCatagory является родительским классом Project Class. Итак, без родительского класса, как может существовать дочерний класс.

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

Ссылки (x => x.Catagory) .Column ("Catagory_id"). Foreignkey ("Id");

здесь Внешний ключ - это ваш идентификатор таблицы ProjectCatagory.

person ankur pancholi    schedule 06.12.2013