Конфигурация NHibernate для однонаправленного отношения один ко многим - PullRequest
18 голосов
/ 17 декабря 2010

Я пытаюсь установить отношения следующим образом.Каждый Мастер элемент имеет один или несколько Деталей элементов:

public class Detail {
    public virtual Guid DetailId { get; set; }
    public virtual string Name { get; set; }
}
public class Master {
    public virtual Guid MasterId { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Detail> Details { get; set; }
}

И сопоставлений:

public class MasterMap : ClassMap<Master> 
{
    public MasterMap() 
    {
        Id(x => x.MasterId);
        Map(x => x.Name);
        HasMany(x => x.Details).Not.KeyNullable.Cascade.All();
    }
}
public class DetailMap : ClassMap<Detail> 
{
    public DetailMap() 
    {
        Id(x => x.Id);
        Map(x => x.Name);
    }
}

Мастер таблица базы данных:

masterId   uniqueidentifier NOT NULL
name       nvarchar(max) NULL

и Detail is:

DetailId   uniqueidentifier NOT NULL
name       nvarchar(max) NULL
MasterId   uniqueidentifier NULL
foreign key (masterId) references [Master]

Мне действительно не нужна ссылка из Detail обратно на Master -другими словами, объекты Detail сами по себе просто не интересны для моего доменного уровня.Они будут всегда доступны через их мастер-объект.

Используя такой код:

Master mast = new Master 
{
    MasterId = new Guid(),
    Name = "test",
    Details = new List<Detail> 
    {
        new Detail { .DetailId = new Guid(), .Name = "Test1" },
        new Detail { .DetailId = new Guid(), .Name = "Test1" }
    }
};

using (transaction == Session.BeginTransaction) 
{
    Session.Save(mast);
    transaction.Commit();
}

Это прекрасно работает, за исключением сумасшедшего ограничения, обозначенного в этот пост : NHibernate делает INSERT и сначала помещает Detail.MasterId в значение NULL, а затем выполняет ОБНОВЛЕНИЕ, чтобы установить для него реальный MasterId.

Действительно, я не хочу записей сведений с NULL MasterIds,поэтому, если я установлю в поле MasterId значение NOT NULL, INSERT to Detail потерпит неудачу, потому что, как я сказал, NHibernate пытается ввести MasterId = NULL.

Я предполагаю, что мой вопрос сводится к следующему:

Как я могу получить приведенный выше пример кода для работы с моей существующей моделью домена (например, без добавления свойства Detail.Master), иПоле Detail.MasterId в базе данных имеет значение NOT NULL?

Есть ли способ заставить Nhibernate просто ввести правильный MasterId в начальную INSERT, вместо того, чтобы потом запускать UPDATE?Есть ли где-нибудь обоснование для этого дизайнерского решения?- Я изо всех сил пытаюсь понять, почему это будет сделано таким образом.

Ответы [ 3 ]

32 голосов
/ 29 сентября 2011

NH3 и выше позволяют корректировать сохраняемые объекты в случае однонаправленного отображения один-ко-многим без раздражающего цикла save null - save - update, если для обоих not-null="true" установлено значение и inverse="false" на <один-ко-многим>

Фрагмент кода FluentNHibernate для этого:

public class MasterMap : ClassMap<Master> 
{
    public MasterMap() 
    {
        Id(x => x.MasterId);
        Map(x => x.Name);
        HasMany(x => x.Details)
            .Not.Inverse()     //these options are very
            .Not.KeyNullable() //important and work only if set together 
            .Not.KeyUpdate()   //to prevent double update
            .Cascade.All();
    }
}
14 голосов
/ 17 декабря 2010

Вы не можете. Чтобы процитировать ссылку из мой ответ на другой вопрос, на который вы ссылались:

Очень важное примечание: Если столбец <key> ассоциации <one-to-many> объявлен NOT NULL, NHibernate может вызвать нарушения ограничений при создании или обновлении ассоциации. Чтобы предотвратить эту проблему, вы должны использовать двунаправленную ассоциацию с многозначным концом (набор или сумка), помеченным как inverse="true". См. Обсуждение двунаправленных ассоциаций далее в этой главе.

Редактировать: Как правильно заметил Хаззик, это изменилось в NHibernate 3 и выше. К сожалению, документы не были обновлены, так что вот Hazzik:

[Если вы установите inverse="false" и not-null на <key>, NH3 и выше будут выполнять только две вставки вместо вставки-вставки-обновления.

4 голосов
/ 27 апреля 2011

Причина, по которой NHibernate делает это таким образом, заключается в том, что:Когда он сохраняет детали, он знает только то, о чем детали знают.Поэтому любые основные ссылки, которые происходят в фоновом режиме, игнорируются.Только когда мастер сохранен, он видит отношение и обновляет элементы коллекции с идентификатором мастера.Что с объектно-ориентированной точки зрения логично.Однако с точки зрения экономии это немного менее логично.Я полагаю, что вы всегда можете подать отчет об ошибке или посмотреть, не был ли он уже подан, и попросить его изменить его.Но я полагаю, что у них есть свои конкретные причины (дизайн / домен).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...