In my system, I have two entities - ShoppingCart and ShoppingCartItem. Fairly generic use-case. However, when I save my ShoppingCart, none of the items are being saved to the DB.
Within my object, I create a new ShoppingCart object.
ShoppingCart cart = CreateOrGetCart();
I then add an existing Product which I got from the database to the start.
cart.AddItem(product);
This is just a simple wrapper to add the item to the IList.
public virtual void AddItem(Product product)
{
Items.Add(new ShoppingCartItem { Quantity = 1, Product = product });
}
I then call SaveOrUpdate on the Repository
Repository.SaveOrUpdate(cart);
Which looks like this:
public T SaveOrUpdate(T entity)
{
Session.SaveOrUpdate(entity);
return entity;
}
I'm using Fluent NHibernate for the mapping:
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();
}
Database Schema (SQL Server 2005) is also fairly generic:
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
When I SaveOrUpdate my ShoppingCart, why isn't any ShoppingCartItems also being saved?
Please help.
Thanks
Ben
UPDATE: Wrapping it in a transaction providng me with some more info:
Cannot insert the value NULL into column 'ShoppingCartId', table 'WroxPizza.dbo.ShoppingCartItems'; column does not allow nulls. INSERT fails. The statement has been terminated.
This is because it's a new cart.
Fluent NHibernate offers an alternative to NHibernate's standard XML mapping files. Rather than writing XML documents, you write mappings in strongly typed C# code. This allows for easy refactoring, improved readability and more concise code.
The hibernate-mapping element allows you to nest several persistent <class> mappings, as shown above. It is, however, good practice to map only a single persistent class, or a single class hierarchy, in one mapping file and name it after the persistent super-class. For example, Cat. hbm. xml, Dog.
I had this exact problem with fluent nhibernate. There appears to be a small bug in mapping one-to-many relationships and the relationships not automatically saving or cascading. See here for a posting about it on the Fluent NHibernate group.
Apparently, there is someone working on the issue!
I can;t say for sure that this is the issue with your code but it looks very similar to a problem I had. Hope that helps some!
Why did you include .Cascade.SaveUpdate()
in the line
References(x => x.Cart, "ShoppingCartId").Cascade.SaveUpdate()
?
Perhaps it confuses NHibernate (or Fluent NHibernate) that there seems to be cascading saves/updates from both ends of your relation?
Configuring your HasMany to cascade ought to be sufficient to achieve what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With