Сопоставление "один ко многим" в NHibernate: проблема с вставкой дочернего элемента

Вот мой код:

Order order = new Order { ... };
OrderItem item = new OrderItem { ... };
order.Items.Add(item);
item.Order = order;

using(var tran = session.BeginTransaction()) {
    session.Save(order);
    // Without this, an exception will be thrown: Unexpected row count: 0; expected: 1
    // session.Save(item);

    tran.Commit();
}

Если я раскомментирую строку session.Save(item), она вставит заказ и его элемент. В противном случае генерируется исключение «Неожиданное количество строк: 0; ожидается: 1».

Если я помечу конец many (свойство Items) как inverse = "true", исключение не будет создано, но будет вставлен только Order! Позиция заказа не будет добавлена ​​в БД.

Если я вызываю session.Save(item), не вызывая session.Save(order), он вставляет и заказ, и его элемент.

Как я могу сохранить заказ и его позиции, не вызывая session.Save(orderItem), а только позвонив session.Save(order)? Спасибо!

Вот мои сопоставления:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Core" assembly="Core">
  <class name="Order" table="[Order]">
    <id name="Id">
      <generator class="assigned" />
    </id>

    <property name="Name" />
    <bag name="Items">
      <key column="CategoryId" />
      <one-to-many class="Core.OrderItem, Core"/>
    </bag>
  </class>

  <class name="OrderItem">
    <id name="Id">
      <generator class="assigned" />
    </id>
    <property name="Title" />
    <many-to-one name="Order" column="OrderId" cascade="save-update" not-null="true" />
  </class>

</hibernate-mapping>

person Mouhong Lin    schedule 11.03.2011    source источник


Ответы (2)


Поскольку у вас нет каскада в коллекции Order.Items, он не будет автоматически создавать элемент для вас при сохранении вашего Order.

Но вы делаете каскад от элемента к порядку, поэтому, когда вы сохраняете элемент, он также обновляет порядок.

Когда вы указали inverse = "true", вы сказали NHibernate не обновлять свойство "Item.Order" автоматически, и что вы будете обрабатывать это вручную. Поэтому Заказ никогда не связывается, когда вы добавляете его в коллекцию, поэтому никогда не появляется там после фиксации.

Думаю, нужно просто добавить:

<bag name="Items" cascade="all">

и он будет создавать, обновлять, удалять элементы, принадлежащие заказам.

РЕДАКТИРОВАТЬ: конечно, каскад идет на сумку, а не на узел «один ко многим».

person jishi    schedule 11.03.2011

Попробуйте поместить каскад в сопоставление заказов:

<bag name="Items" cascade="all">
  <key column="CategoryId" />
  <one-to-many class="Core.OrderItem, Core"/>
</bag>
person Florian Lim    schedule 11.03.2011