Когда использовать inverse = "true | false"
Атрибут inverse
используется, чтобы помочь NHibernate узнать, какую сторону отношений следует использовать для сохранения отношений. Не обратная сторона (обратите внимание на двойной отрицательный) - это сторона, которая будет сохраняться. Если ни одна из сторон не является обратной, то связь будет сохраняться дважды, как в случае INSERT
, за которым сразу же следует приведенный выше пример UPDATE
. Если обе стороны обратные, связь вообще не будет сохраняться, поэтому важно правильно установить обратное.
Мне нравится думать о inverse
следующим образом. Я не знаю, официально это работает или нет, но это помогает моему миру понять:
многие к один
many-to-one
отношения всегда inverse="false"
. Они всегда используются для сохранения связи с базой данных. Поскольку они всегда inverse="false"
, указывать их не нужно, поэтому NHibernate (и, следовательно, Fluent NHibernate) не предоставляет для него опцию.
(Я сталкивался только с одной ситуацией, в которой мне хотелось бы указать inverse="true"
для many-to-one
. Если у вас есть one-to-many
list
с одной стороны и many-to-one
с другой Кроме того, вы должны позволить list
управлять отношениями, чтобы NHibernate мог позаботиться о настройке для вас значений index
. В текущем состоянии вам нужно добавить свойство в дочерний класс и управлять index
ценит себя.)
один-к-одному
one-to-one
отношения всегда inverse="true"
. Они никогда не существуют без id
или many-to-one
на другой стороне отношений, которые позаботятся о сохранении отношений. Поскольку значение inverse
всегда одинаково, указывать его не нужно, поэтому указание его не поддерживается.
Коллекция
Коллекции, такие как bag
, list
, set
и т. Д., Могут быть или не быть частью двунаправленных отношений. Если они существуют самостоятельно (возможно, мешок строковых элементов), то они должны быть inverse="false"
(по умолчанию), потому что никто не будет нести ответственность за сохранение отношений. Если они существуют в сочетании с другими отношениями, однако (как и ваши традиционные отношения один-ко-многим / многие-к-одному) они должны быть указаны как inverse="true"
.
Для many-to-many
коллекций, где у вас есть коллекция по обе стороны отношения, пометьте одну из них как inverse="true"
, а другую оставьте по умолчанию inverse="false"
. Опять же, дело в том, что одна сторона отношений должна быть не обратной. Какую сторону выбрать? Например, если мы возьмем отношения «многие ко многим» между пользователями и ролями, у вас, вероятно, будет много пользователей и несколько ролей. По моему мнению, вы должны сопоставить Role.Users
как inverse="true"
и позволить User.Roles
контролировать отношения, так как это меньший набор данных для работы и, вероятно, в любом случае вам важнее коллекция.
(На самом деле, я бы вообще не хотел включать в модель Role.Users
. Предположим, что роль «Клиент» имеет 100 000 пользователей. Тогда customerRole.Users
- непригодная бомба с ленивым зарядом, ожидающая взрыва. )
... вернуться к вашему вопросу ...
Так как на самом деле не имеет значения, какая сторона отношения обратная, только если одна сторона не обратная, тогда вы должны сделать сторону one-to-one
обратной, поскольку NHibernate хочет именно так , Не боритесь с инструментом за вещи, которые не имеют значения. В предоставленных вами сопоставлениях по существу обе стороны отношения были помечены как не обратные, что привело к тому, что отношение сохранялось дважды. Следующие отображения должны работать лучше для вас:
public class Parent
{
public virtual Guid Id { get; set; }
public virtual Child Child { get; set; }
}
public class ParentClassMap : ClassMap<Parent>
{
public ParentClassMap()
{
Id(x => x.Id);
HasOne(x => x.Child)
.PropertyRef(x => x.Parent)
.Cascade.All();
}
}
public class Child
{
public virtual Guid Id { get; set; }
public virtual Parent Parent { get; set; }
}
public class ChildClassMap : ClassMap<Child>
{
public ChildClassMap()
{
Id(x => x.Id);
References(x => x.Parent)
.Not.Nullable()
.Unique()
.Cascade.SaveUpdate();
}
}
... что приводит к следующему SQL из вашего кода вставки теста:
exec sp_executesql N'INSERT INTO [Parent] (Id) VALUES (@p0)',N'@p0 uniqueidentifier',@p0='925237BE-558B-4985-BDA2-9F36000797F5'
exec sp_executesql N'INSERT INTO [Child] (Parent_id, Id) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='925237BE-558B-4985-BDA2-9F36000797F5',@p1='BE6D931A-8A05-4662-B5CD-9F36000797FF'
Нет запроса на обновление!