NHibernate:使用Fluent Nhibernate来保存子对象

时间:2009-02-08 01:51:23

标签: nhibernate fluent-nhibernate nhibernate-mapping

在我的系统中,我有两个实体 - 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时,为什么还没有保存任何ShoppingCartItem?

请帮忙。

由于

更新: 在交易中包装它可以提供更多信息:

  

无法将值NULL插入“ShoppingCartId”列表中   'WroxPizza.dbo.ShoppingCartItems';列不允许空值。   INSERT失败。声明已经终止。

这是因为它是一个新推车。

8 个答案:

答案 0 :(得分:3)

我有流利的nhibernate这个确切的问题。在映射一对多关系以及关系不会自动保存或级联时似乎存在一个小错误。 See here for a posting about it on the Fluent NHibernate group

显然,有人在处理这个问题!

我可以确定这是您的代码问题,但it looks very similar to a problem I had。希望有所帮助!

答案 1 :(得分:2)

为什么在行

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

也许让NHibernate(或Fluent NHibernate)感到困惑的是,你的关系的两端似乎都有级联的保存/更新?

将HasMany配置为级联应该足以实现您想要的目标。

答案 2 :(得分:1)

尝试在事务中包装Session.SaveOrUpdate,或者在。之后直接强制刷新。

答案 3 :(得分:0)

我不确定,但我认为NHibernate不会将对象保存到子对象。你没有显示调用SaveOrUpdate的代码,但我知道你是否在那时循环遍历ShoppingCartItems,单独保存每个,然后它们也会被保留。

答案 4 :(得分:0)

我知道没有关于NHibernate(我使用的OPF为我做了这个),但是当你保存聚合根(ShoppingCart)时代码也应该提交它的情况不是这样的情况还拥有会话的实例?

答案 5 :(得分:0)

您的购物车是否可能先保存,然后是购物车?因此子项目没有父ID可供使用?

您可能需要在创建时将购物车明确保存回数据库,然后将商品添加到其中并保存 - 只是为了获取ID。

答案 6 :(得分:0)

注意,您使用Identity定义了(在数据库模式中)字段,因此,必须在Map文件中设置这些字段。示例如下:

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

您收到的错误是因为您没有在Identity中设置映射中的Identity字段,因此,当您尝试Save()时,不会生成Identity列(并且在其中设置为非null)数据库)然后它会给你错误。

答案 7 :(得分:-4)

问题出在sessionfactory的配置语句中。如果您希望数据保持不变,请不要使用Exposeconfiguration。这肯定会解决您的数据持久性问题。