У меня проблема с тем, что должно быть довольно простым (я бы подумал) сценарием использования NHibernate.
У меня есть классическая сущность Parent и Child, например:
public class Parent
{
public virtual int ParentId { get; set; }
public virtual string Name { get; set; }
public virtual IList<Child> Children { get; set; }
}
public class Child
{
public virtual int ChildId { get; set; }
public virtual Parent Parent { get; set; }
public virtual string Name { get; set; }
}
И отображения следующим образом:
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Id(x => x.ParentId).GeneratedBy.Native();
Map(x => x.Name);
HasMany(x => x.Children).KeyColumn("ParentId").Cascade.SaveUpdate();
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
Id(x => x.ChildId).GeneratedBy.Native();
Map(x => x.Name);
References(x => x.Parent).Column("ParentId").ReadOnly().Not.Nullable();
}
}
Наконец, у меня есть простые тесты:
[Test]
public void Test_save_family()
{
var parent = new Parent();
var child = new Child {Parent = parent};
parent.Children = new List<Child>{child};
SessionManager.WithSession(
session =>
{
session.Save(parent);
session.Flush();
});
}
Сбой теста с System.Data.SqlClient.SqlException: Невозможно вставить значение NULLв столбец «ParentId».Это верно в том смысле, что столбец не имеет значения NULL, но почему он вставляет значение NULL?
Если я удаляю ограничение NULL, сохранение работает, поскольку NHibernate сначала вставляет родительский элемент, затем вставляет дочерний элемент, а затем обновляет ParentIdстолбец дочерней записи, как показано в следующих выходных данных:
NHibernate: INSERT INTO [Parent] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL
NHibernate: INSERT INTO [Child] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL
NHibernate: UPDATE [Child] SET ParentId = @p0 WHERE ChildId = @p1;@p0 = 2, @p1 = 1
Мне это кажется странным, так как почти во всех случаях столбцы внешнего ключа этого вида объявляются не обнуляемыми, и поэтому внешний ключ должен быть предоставлен ввставить.Так почему же NHibernate не устанавливает внешний ключ при начальной вставке дочерней строки и как это исправить?