Подтвердить что ты не робот

NHibernate: использование Fluent Nhibernate для сохранения дочерних объектов

В моей системе у меня есть два объекта - ShoppingCart и ShoppingCartItem. Довольно общий прецедент. Однако, когда я сохраняю свой ShoppingCart, ни один из элементов не сохраняется в БД.

В моем объекте я создаю новый объект ShoppingCart.

ShoppingCart cart = CreateOrGetCart();

Затем я добавляю существующий Продукт, который я получил от базы данных до начала.

cart.AddItem(product);

Это просто простая оболочка для добавления элемента в IList.

    public virtual void AddItem(Product product)
    {
        Items.Add(new ShoppingCartItem { Quantity = 1, Product = product });
    }

Затем я вызываю SaveOrUpdate в репозитории

Repository.SaveOrUpdate(cart);

Что выглядит так:

   public T SaveOrUpdate(T entity)
    {
        Session.SaveOrUpdate(entity);
        return entity;
    }

Я использую Fluent NHibernate для отображения:

    public ShoppingCartItemMap()
    {
        WithTable("ShoppingCartItems");

        Id(x => x.ID, "ShoppingCartItemId");
        Map(x => x.Quantity);

        References(x => x.Cart, "ShoppingCartId").Cascade.SaveUpdate();
        References(x => x.Product, "ProductId");
    }


    public ShoppingCartMap()
    {
        WithTable("ShoppingCarts");

        Id(x => x.ID, "ShoppingCartId");
        Map(x => x.Created);
        Map(x => x.Username);

        HasMany<ShoppingCartItem>(x => x.Items)
            .IsInverse().Cascade.SaveUpdate()
            .WithKeyColumn("ShoppingCartId")
            .AsBag();
    }

Схема базы данных (SQL Server 2005) также является довольно общей:

CREATE TABLE [dbo].[ShoppingCarts]
(
[ShoppingCartID] [int] NOT NULL IDENTITY(1, 1),
[Username] [nvarchar] (50) NOT NULL,
[Created] [datetime] NOT NULL
)
GO
ALTER TABLE [dbo].[ShoppingCarts] ADD CONSTRAINT [PK_ShoppingCarts] PRIMARY KEY CLUSTERED ([ShoppingCartID])
GO



CREATE TABLE [dbo].[ShoppingCartItems]
(
[ShoppingCartItemId] [int] NOT NULL IDENTITY(1, 1),
[ShoppingCartId] [int] NOT NULL,
[ProductId] [int] NOT NULL,
[Quantity] [int] NOT NULL
)
GO
ALTER TABLE [dbo].[ShoppingCartItems] ADD CONSTRAINT [PK_ShoppingCartItems] PRIMARY KEY CLUSTERED ([ShoppingCartItemId])
GO
ALTER TABLE [dbo].[ShoppingCartItems] ADD CONSTRAINT [FK_ShoppingCartItems_Products] FOREIGN KEY ([ProductId]) REFERENCES [dbo].[Products] ([ProductId])
GO
ALTER TABLE [dbo].[ShoppingCartItems] ADD CONSTRAINT [FK_ShoppingCartItems_ShoppingCarts] FOREIGN KEY ([ShoppingCartId]) REFERENCES [dbo].[ShoppingCarts] ([ShoppingCartID])
GO

Когда я SaveOrUpdate моей ShoppingCart, почему не сохраняются какие-либо ShoppingCartItems?

Пожалуйста, помогите.

Спасибо

Бен

UPDATE: Обертывая его в транзакции, предоставляя мне дополнительную информацию:

Невозможно вставить значение NULL в столбец "ShoppingCartId", таблицу 'WroxPizza.dbo.ShoppingCartItems'; столбец не допускает нулей. INSERT терпит неудачу. Заявление завершено.

Это потому, что это новая тележка.

4b9b3361

Ответ 1

У меня была эта точная проблема с беглостью nhibernate. Кажется, существует небольшая ошибка при сопоставлении отношений "один ко многим", а отношения не сохраняются автоматически или каскадируются. См. здесь публикацию об этом в группе Fluent NHibernate.

По-видимому, кто-то работает над проблемой!

Я не могу сказать, что это проблема с вашим кодом, но он очень похож на проблему, которую я имел. Надеюсь, что это поможет!

Ответ 2

Почему вы включили .Cascade.SaveUpdate() в строку

References(x => x.Cart, "ShoppingCartId").Cascade.SaveUpdate()

?

Возможно, это смущает NHibernate (или Fluent NHibernate), что, кажется, каскадные сбережения/обновления с обоих концов вашего отношения?

Настройка вашего HasMany в каскад должна быть достаточной для достижения желаемого.

Ответ 3

Попробуйте обернуть Session.SaveOrUpdate в транзакции или принудительно выполнить сброс сразу после.

Ответ 4

Я не уверен, но я не думаю, что NHibernate каскадирует сохранение объектов дочерним объектам. Вы не показываете код, который вызывает SaveOrUpdate, но я знаю, что если вы зацикливаете объекты ShoppingCartItems в этот момент, сохраняя их индивидуально, они также будут сохранены.

Ответ 5

Я знаю ничего о NHibernate (OPF, который я использую для этого, для меня), но не так ли, когда вы сохраняете корень агрегата (ShoppingCart), этот код должен также совершать его и на сессию тоже?

Ответ 6

Возможно ли, что ваши товары корзины сначала сохраняются, а затем тележка? поэтому дочерние элементы не имеют родительского идентификатора для использования?

Вам необходимо явно сохранить корзину обратно в БД при создании, затем добавить элементы в нее и сохранить - только для получения идентификатора.

Ответ 7

Как уже отмечалось, вы определили поля (в схеме базы данных) с идентификатором, поэтому эти поля должны быть установлены в файле карты. Пример:

Id(x => x.ID, "ShoppingCartItemId").GeneratedBy.Identity();

ошибка, которую вы получаете, потому что вы не задали поля Identity в сопоставлении, которые должны быть сгенерированы с помощью Identity, поэтому при попытке Save() столбец Identity не генерируется (и устанавливается не null в база данных), то она дает вам ошибку.

Ответ 8

Проблема заключается в вашей инструкции конфигурации sessionfactory. Не используйте Exposeconfiguration, если вы хотите, чтобы ваши данные сохранялись. Это наверняка решит вашу проблему сохранения данных.