Почему моя коллекция сумок NHibernate не устанавливает «родительский идентификатор» для дочерних элементов динамически?

У меня есть новый объект с коллекцией новых объектов внутри него в некотором свойстве как IList. Я вижу, что через sql profiler выполняются два запроса на вставку ... один для родительского элемента, у которого есть новый идентификатор guid, и один для дочернего элемента, однако внешний ключ дочернего элемента, который ссылается на родительский элемент, является пустым идентификатором GUID. Вот мое отображение на родителя:

<id name="BackerId">
  <generator class="guid" />
</id>
<property name="Name" />
<property name="PostCardSizeId"  />
<property name="ItemNumber" />

<bag name="BackerEntries" table="BackerEntry" cascade="all" lazy="false" order-by="Priority">
  <key column="BackerId" />
  <one-to-many class="BackerEntry" />
</bag> 

В классе Backer.cs я определил свойство BackerEntries как

IList<BackerEntry>

Когда я пытаюсь SaveOrUpdate переданного объекта, я получаю следующие результаты в профилировщике sql:

exec sp_executesql N'INSERT INTO Backer (Name, PostCardSizeId, ItemNumber, BackerId) VALUES (@ p0, @ p1, @ p2, @ p3) ', N' @ p0 nvarchar (3), @ p1 uniqueidentifier, @ p2 nvarchar (3 ), @ p3 uniqueidentifier ', @ p0 = N'qaa', @ p1 = 'BC95E7EB-5EE8-44B2-82FF30F5176684D', @ p2 = N'qaa ', @ p3 =' 18FBF8CE-FD22-4D08-A3B1-63D6DFF426

exec sp_executesql N'INSERT INTO BackerEntry (BackerId, BackerEntryTypeId, Name, Description, MaxLength, IsRequired, Priority, BackerEntryId) ЗНАЧЕНИЯ (@ p0, @ p1, @ p2, @ p3, @ p4, @ p5, @ p6, @ p6, @ p6, @ p6, @ p6 ', N' @ p0 uniqueidentifier, @ p1 uniqueidentifier, @ p2 nvarchar (5), @ p3 nvarchar (5), @ p4 int, @ p5 bit, @ p6 int, @ p7 uniqueidentifier ', @ p0 =' 00000000-0000 -0000-0000-000000000000 ', @ p1 =' 2C5BDD33-5DD3-42EC-AA0E-F1E548A5F6E4 ', @ p2 = N'qaadf', @ p3 = N'wasdf ', @ p4 = 0, @ p5 = 1, @ p6 = 0, @ p7 = 'FE9C4A35-6211-4E17-A75A-60CCB526F1CA'

Как видите, это не сбрасывает пустой идентификатор для BackerId дочернего элемента на новый реальный идентификатор родительского элемента.

Наконец, исключение составляет:

"NHibernate.Exceptions.GenericADOException: could not insert: [CB.ThePostcardCompany.MiddleTier.BackerEntry][SQL: INSERT INTO BackerEntry (BackerId, BackerEntryTypeId, Name, Description, MaxLength, IsRequired, Priority, BackerEntryId) VALUES (?, ?, ?, ?, ?, ?, ?, ?)] ---\u003e System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint

РЕДАКТИРОВАТЬ: РЕШЕНО! Первый ответ ниже указал мне правильное направление. Мне нужно было добавить эту обратную ссылку на дочернее сопоставление и класс. Это позволило ему работать исключительно в формате .net - однако при приеме json произошло отключение, поэтому мне пришлось придумать какой-то необычный код, чтобы «повторно подключить» детей.


person EvilSyn    schedule 28.09.2008    source источник


Ответы (2)


Возможно, вам потребуется добавить NOT-NULL = "true" в свой класс сопоставления:

<bag name="BackerEntries" table="BackerEntry" cascade="all" lazy="false" order-by="Priority">
  <key column="BackerId" not-null="true"/>
  <one-to-many class="BackerEntry" />
</bag>

а также убедитесь, что у вас есть обратное сопоставление, определенное для дочернего класса:

<many-to-one name="parent" column="PARENT_ID" not-null="true"/>

У меня были аналогичные проблемы со спящим режимом в моем текущем проекте с отношениями родитель-потомок, и это было частью решения.

person Elie    schedule 28.09.2008
comment
Спасибо .. Вы указали мне правильное направление ... У меня не было обратной ссылки в моем дочернем картировании. - person EvilSyn; 29.09.2008

У меня была эта проблема, и мне потребовалась целая вечность, чтобы понять. Дочерняя таблица должна допускать пустые значения для родительского внешнего ключа. NHibernate любит сохранять дочерние элементы с NULL в столбце внешнего ключа, а затем возвращаться и обновлять с правильным ParentId.

person RyanL    schedule 17.11.2010
comment
определенно неверно, вам нужно отобразить двунаправленную ассоциацию так, чтобы обратный конец был родительским, и установить свойства с обеих сторон. nhforge.org/doc/nh/en/index.html# коллекции-двунаправленные - person dotjoe; 10.05.2012
comment
+1. Да, это правда. Чтобы это работало, столбец FK в дочерней таблице должен допускать значение NULL. NHibernate добавляет дочерний элемент с ParentID, установленным в NULL, а затем обновляет ParentID, когда Parent фактически сохраняется в базе данных. - person Dejan Janjušević; 17.04.2015