Свободный NHibernate HasMany не обновляет FK - PullRequest
2 голосов
/ 22 апреля 2009

Я использую последнюю версию Fluent NHibernate lib (0.1.0.452), и у меня проблема с сохранением дочерних прав.

Я думаю, что это довольно распространенный сценарий ... У меня есть родитель с отображением:

HasMany<Packet>(x => x.Packets)
            .Cascade.All()
            .KeyColumnNames.Add("OrderId");

и простой класс Packet, который (в модели предметной области и сопоставлении FNH) не имеет никакой ссылки на родителя. То, что генерируется, является правильной таблицей Пакетов, которая содержит столбец с именем OrderId. Что не работает, так это экономия. Всякий раз, когда я пытаюсь сохранить родительский объект, дети также сохраняются, но FK остается без изменений. Я проверил SQL и в операторе INSERT OrderId даже не отображается!

INSERT INTO KolporterOrders (CargoDescription, SendDate, [more cols omitted] ) VALUES ('order no. 49', '2009-04-22  00:57:44', [more values omitted])
SELECT LAST_INSERT_ID()
INSERT INTO Packets (Weight, Width, Height, Depth) VALUES ('To5Kg', 1, 1, 1)
SELECT LAST_INSERT_ID()

Как вы видите, OrderId полностью отсутствует в последней вставке.

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

<bag name="Packets" cascade="all">
    <key column="OrderId" />
    <one-to-many class="Company.Product.Core.Packet, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

Я попытался установить Cascade на разные значения. Я даже добавил ссылки в PacketMap (класс отображения FNH).

Есть идеи, почему не добавляется OrderId?

Редактировать: забыл упомянуть: я использую MySQL5, если это имеет значение.

Edit2: Приведенное выше отображение FNH генерирует hbm с сумкой (не набором) - я редактировал его. Код C #, используемый для сохранения:

var order = new Order(); 
NHSession.Current.SaveOrUpdate(order); //yes, order.Packets.Count == 1 here

///Order.cs, Order ctor
public Order()
    {
        CreateDate = DateTime.Now;
        OrderState = KolporterOrderState.New;
        Packets = new List<Packet>();
        Packets.Add(new Packet()
        {
            Depth = 1,
            Height = 1,
            Width = 1,
            Weight = PacketWeight.To5Kg
        });
    }

сеанс сбрасывается и закрывается в EndRequest.

Ответы [ 3 ]

2 голосов
/ 22 апреля 2009

Хорошо, моя вина. Я тестировал его в ApplicationStart файла global.asax, поэтому запрос не был создан, поэтому сеанс не был сброшен. Я понял это, когда протестировал его на простом проекте ConsoleApp, когда увидел, что сброс данных действительно вызывает обновление FK col.

В любом случае: спасибо за помощь!

0 голосов
/ 22 апреля 2009

Это действительно странно. Вы должны проверить последующие обновления, NHibernate иногда обновляет внешние ключи, а затем он не появляется во вставке.

Убедитесь, что OrderId не имеет нескольких значений в таблице Packets. Чтобы проверить это, измените имя OrderId на другое.

Каскад не имеет к этому никакого отношения. Он контролирует только если вам нужно явно сохранить ребенка.

0 голосов
/ 22 апреля 2009

В "ванильной" объектной модели parent-children вы должны обновить ссылку дочернего объекта на parent, чтобы NHibernate обновил ссылку дочерней записи на parent.

В "инвертированной" объектной модели parent-children необходимо изменить коллекцию дочерних объектов parent, чтобы заставить NHibernate обновлять ссылки дочерних записей на родительский.

Возможно, вы захотите использовать "инвертированную" объектную модель parent-children.

В отображении XML вам нужно

<set name="Packets" cascade="all" inverse="true">
    <key column="OrderId" />
    <one-to-many class="Company.Product.Core.Packet, Core,
        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>

В отображении Fluent вам нужно

HasMany<Packet>(x => x.Packets)
    .Cascade.All()
    .Inverse()
    .KeyColumnNames.Add("OrderId")
;
...