2009-02-08 11 views
19

Nel mio sistema, ho due entità: ShoppingCart e ShoppingCartItem. Caso d'uso abbastanza generico. Tuttavia, quando salgo la ShoppingCart, nessuno degli elementi viene salvato nel DB.NHibernate: utilizzo di Fluent Nhibernate per salvare oggetti figlio

All'interno dell'oggetto, creo un nuovo oggetto ShoppingCart.

ShoppingCart cart = CreateOrGetCart(); 

Aggiungo quindi un prodotto esistente che ho ottenuto dal database all'inizio.

cart.AddItem(product); 

Questo è solo un semplice wrapper per aggiungere l'elemento all'IList.

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

Ho poi chiamo SaveOrUpdate sul Repository

Repository.SaveOrUpdate(cart); 

che assomiglia a questo:

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

sto utilizzando Fluent NHibernate per la mappatura:

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(); 
    } 

Schema del database (SQL Server 2005) è anche abbastanza generico:

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 

Quando ho saveOrUpdate il mio carrello, perché non è alcun ShoppingCartItems anche essere salvati?

Per favore aiuto.

Grazie

Ben

UPDATE: avvolgendolo in una transazione me providng con qualche informazione in più:

Impossibile inserire il valore NULL nella colonna 'ShoppingCartId', tavolo 'WroxPizza .dbo.ShoppingCartItems'; la colonna non consente null. INSERT fallisce. La dichiarazione è stata chiusa.

Questo perché si tratta di un nuovo carrello.

+0

La soluzione di James Gregorys ha funzionato per me. –

risposta

1

Provare a eseguire il wrapping di Session.SaveOrUpdate in una transazione o forzare lo svuotamento direttamente dopo.

0

Non sono sicuro, ma non credo che NHibernate faccia cadere il salvataggio di oggetti su oggetti figlio. Non mostri il codice che chiama SaveOrUpdate, ma so se esegui il loop di ShoppingCartItems a quel punto, salvandoli singolarmente, anche loro verranno mantenuti.

0

so nulla su NHibernate (L'OPF che uso fa questo per me), ma non è il caso che quando si salva la radice aggregata (ShoppingCart) che il codice dovrebbe anche impegnarsi sue istanze modo composto di proprietà al sessione anche tu?

0

È possibile che le voci del carrello salgano prima, quindi il carrello? quindi gli articoli figli non hanno ID genitori da usare?

È possibile che sia necessario salvare esplicitamente il carrello sul DB al momento della creazione, quindi aggiungere gli elementi al suo interno e salvare - solo per ottenere l'ID.

2

Perché si includono .Cascade.SaveUpdate() nella linea

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

?

Forse confonde NHibernate (o Fluent NHibernate) che sembra che ci siano salvataggi/aggiornamenti a cascata da entrambe le estremità della relazione?

Configurare il tuo HasMany in cascata dovrebbe essere sufficiente per ottenere ciò che desideri.

-4

Il problema riguarda l'istruzione di configurazione di sessionfactory. Non usare Exposeconfiguration se vuoi che i tuoi dati persistano. Questo sicuramente risolverà il tuo problema di persistenza dei dati.

+0

l'uso di schemaexport dovrebbe essere fatto con attenzione. –

0

Come notato, sono stati definiti (nei campi dello schema del database) campi con Identità, pertanto, questi campi devono essere impostati nel file Mappa. Esempio come il seguente:

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

l'errore hai trovato perché non hai impostato i campi di identità nella mappatura per essere generato da Identità, in tal modo, quando si sta cercando di salvare(), l'identità la colonna non viene generata (e impostata su null nel database) quindi ti dà l'errore.