5

Ho un rapporto molti per molti:Come eliminare in una relazione molti a molti?

Il prodotto ha molte categorie e la categoria ha molti prodotti.

Dire che ho

Shopping Category 
Food Category 

Product A - Shopping Category, Food Category 
Product B - Shopping Category 

Ora cancello Shopping Category. Voglio il riferimento Product A da rimuovere da Shopping Category e voglio che Product B sia rimosso completamente.

Vorrei finire con:

Product A - Food Category. 

Come faccio a fare questo in NHibernate (sto usando NHibernate fluente).

Ho tentato di utilizzare Cascade DeleteOrphan e AllDeleteOrphan ma quando lo faccio ed elimini Shopping entrambi i prodotti A e B vengono eliminati.

public class CategoryMapping : ClassMap<Category> 
{ 
    public CategoryMapping() 
    { 
     Id(x => x.Id).GeneratedBy.GuidComb(); 

     Map(x => x.Name).Not.Nullable().NvarcharWithMaxSize(); 
     HasManyToMany(x => x.Products).Cascade.DeleteOrphan(); 
    } 
} 


public class ProductMapping : ClassMap<Product> 
{ 
    public ProductMapping() 
    { 
     Id(x => x.Id).GeneratedBy.GuidComb(); 
     Map(x => x.Name).Not.Nullable().NvarcharWithMaxSize(); 
     HasManyToMany(x => x.Categories); 
    } 
} 

    unitOfWork.BeginTransaction(); 
    Category category =session.Load<Category>(id); 
    session.Delete(category); 
    unitOfWork.Commit(); 

risposta

2

Non penso che questo possa essere gestito mappando con la struttura dati esistente. Penso che avresti bisogno di scrivere del codice manuale (*) o cambiare la struttura dei dati.

(*) Non è sicuro al 100% che funziona però ...

unitOfWork.BeginTransaction(); 
Category category =session.Load<Category>(id); 
var productsDel = category.Products.Where(p => p.Categories.Count == 1); 
productsDel.ForEach(p => session.Delete(p)); 
session.Delete(category); 
unitOfWork.Commit(); 

Altro:

Sto anche pensando di aggiungere la mappatura per le tabelle di cross-ref. Quindi dovresti essere in grado di configurare la mappatura in modo da eliminare solo i record da quella tabella di cross-ref. Dovrai verificare se ci sono prodotti senza riferimenti e cancellarli periodicamente. (alcuni codici di pulizia periodici, come l'esecuzione di alcune stored procedure). So che queste soluzioni hanno un cattivo odore :) Ci sono ancora trigger e altre cose su SQL Server ... non buone soluzioni comunque, ma soluzioni.

0

Se si desidera solo per rimuovere l'associazione tra i due utilizzo Cascade.SaveUpdate()

Poi basta rimuovere il soggetto dalla raccolta e il commit della transazione se si utilizza le transazioni se non hai bisogno di fare una sessione .Flush

+0

Non capisco. Ho pensato che saveUpdate avrebbe ripreso il tutto e non sono sicuro di cosa intendi rimuovendo l'entità dalla raccolta. Potrei avere 1000 di prodotti che hanno bisogno del loro riferimento per essere rimossi quando elimino il sistema di aggancio, quindi questo sembra essere ciò che una cascata sarebbe per me che dovrei farlo io stesso. – chobo2

+0

Forse ho frainteso la tua domanda, ma posso sicuramente capire perché 'DeleteOrphan' e' AllDeleteOrphan' eliminano il prodotto A in questa istanza. 'SaveUpdate' cancellerà solo le associazioni (le voci da molti a molti della tabella ...' product_category') ma non cancellerà 'Prodotto A'. Questo è qualcosa che dovresti gestire manualmente quando usi questa impostazione a cascata. Non penso che ci sia una cascata che gestisce questo (potrebbe essere sbagliato però). –

+0

Hmm Dovrò provarlo ma pensavo che DeleteOrphan fosse esattamente per questa situazione. Non lo vedo come per me Prodotto A non è un orfano in quanto ha ancora una relazione con qualcosa. – chobo2