Я пытаюсь заставить NHibernate использовать многие стороны коллекции для управления двунаправленной ассоциацией для моделирования отношения "один к одному".
Родительский класс и карта:
public class Parent
{
private ICollection<Child> children;
public Parent()
{
this.children = new HashedSet<Child>();
}
public virtual Guid Id { get; protected internal set; }
public virtual Child Child
{
get { return children.FirstOrDefault(); }
set
{
{
this.children.Clear();
if (value != null)
{
this.children.Add(value);
}
}
}
}
}
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
this.Id(x => x.Id)
.GeneratedBy.GuidComb();
this.HasMany<Child>(Reveal.Member<Parent>("children"))
.Access.Field()
.Cascade.All()
.Not.Inverse()
.AsSet();
}
}
Детский класс и карта:
public class Child
{
public virtual Guid Id { get; protected internal set; }
public virtual Parent Parent { get; set; }
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
this.Id(x => x.Id)
.GeneratedBy.GuidComb();
this.References(x => x.Parent)
.Not.Nullable()
.Cascade.All();
}
}
Следующий код создает две вставки и обновление:
var parent = new Parent();
var child = new Child();
parent.Child = child;
child.Parent = parent;
session.Save(parent);
session.Flush();
Обратите внимание на дублирующий SQL-код для второй вставки и следующее обновление:
exec sp_executesql N'INSERT INTO [Parent] (Id) VALUES (@p0)',N'@p0 uniqueidentifier',@p0='AA5A146E-E3F5-4373-B7A8-9EF301171401'
go
exec sp_executesql N'INSERT INTO [Child] (Parent_id, Id) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='AA5A146E-E3F5-4373-B7A8-9EF301171401',@p1='B78C4461-A217-47FC-BE02-9EF30117140A'
go
exec sp_executesql N'UPDATE [Child] SET Parent_id = @p0 WHERE Id = @p1',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='AA5A146E-E3F5-4373-B7A8-9EF301171401',@p1='B78C4461-A217-47FC-BE02-9EF30117140A'
go
Пока этот код создает печально известный not-null property references a null or transient value inverse
:
var parent = new Parent();
var child = new Child();
parent.Child = child;
//child.Parent = parent;
session.Save(parent);
session.Flush();
Я нашел множество сообщений об этом, но еще не нашел окончательного руководства о том, как делать нуль-к-одному, с inverse=false
на стороне one
.
Я пробовал метод "один-ко-многим/один-к-одному", упомянутый здесь.
Кроме того, я нашел несколько открытых проблем в NHibernate о (не) nullable Foreign Keys: NH-941, NH-1050 и т.д.
Что я делаю неправильно?
Редактировать 2011-05-30
Итак, мое временное решение состоит в том, чтобы пойти на стандартную настройку inverse=true
на много сторон и сделать некоторую магию в настройщике родителя:
public virtual Child Child
{
get { return children.FirstOrDefault(); }
set
{
{
this.children.Clear();
if (value != null)
{
value.Parent = this;
this.children.Add(value);
}
}
}
}
Но я все еще сбиваюсь с толку по поведению inverse=false
, которое должно быть эквивалентно inverse=true
на стороне много-друг (интересно, FluentNhibernate не позволяет ManyToOnePart устанавливать inverse=true
как этот рекомендует).