2015-05-05 9 views
5

I have Two Table, tableA e tableB.Impossibile eliminare la raccolta: [NHibernate.Exceptions.GenericADOException]

tableA avere colonna: tabAId, col2, col3 (tabAId primaryKey e la colonna di identità.)

tableB hanno colonna: tabAId, nome (tabAId non è nullo)

devo creare Bag nel file hbm di tableA, per mantenere la relazione ship.

<bag name="tableB" lazy="true" inverse="false" 
        batch-size="25" cascade="all-delete-orphan"> 
    <key column="tabAId" /> 
    <one-to-many class="tableB" /> 
</bag> 

Quando provo ad aggiornare il record in tableA è un'eccezione tiro, dove, come ho lista di bambino in caso tableA.

[NHibernate.Exceptions.GenericADOException] = { "non ha potuto eliminare collezione: [MIHR.Entities.tableA.tableB 21 #] [SQL: UPDATE dbo.tableB SET tabAId = null DOVE tabAId = @ p0]" }

InnerException = { "Impossibile inserire il valore NULL nella colonna 'tabAId', tabella 'SA_MIHR_DEV.dbo.tableB';... colonna non consente i null aggiornamento non riesce \ r dichiarazione \ nIl è stata terminata" }

risposta

8

Ci sono solo due modi per risolvere questo problema.

1) Non utilizzare inverse="false"

<bag name="tableB" lazy="true" inverse="true" // instead of false 
        batch-size="25" cascade="all-delete-orphan"> 
    <key column="tabAId" /> 
    <one-to-many class="tableB" /> 
</bag> 

Questa impostazione (inverse = "true") istruirà NHibernate per eliminare direttamente un oggetto da DB.

Durante l'utilizzo inverse="false" sarà in generale sempre comportare:

  • UPDATE (con null) == atto di rimozione dalla collezione
  • voce DELETE == atto di cascata

2) rendere nullable la colonna di riferimento

Ciò significa che possiamo lasciare NHibernate per fare UPDATE e DELETE. Perché la colonna ora è nullable.

Questi sono solo due modi per risolverlo qui.

La mia preferenza sarebbe: inverse = "true"

per funzionare correttamente con inverse="true" dobbiamo sempre di assegnare entrambi i lati della relazione in C#.Questo è un must per Add(), operazione INSERT:

Parent parent = new Parent(); 
Child child = new Child 
{ 
    ... 
    Parent = parent, 
}; 
// unless initialized in the Parent type, we can do it here 
parent.Children = parent.Children ?? new List<Child>(); 
parent.Children.Add(child); 

// now just parent could be saved 
// and NHibernate will do all the cascade as expected 
// and because of inverse mapping - the most effective way 
session.Save(parent); 

Come possiamo vedere, noi abbiamo assegnato - esplicitamente - entrambi i lati della relazione. Questo è necessario per trarre profitto dalla mappatura inversa di NHibernate. Ed è anche una buona pratica, perché in seguito, caricando i dati dal DB, ci aspettiamo che NHibernate si occuperà di impostarlo per noi

+1

Se imposto Inverse = "true", allora non inserirà il valore della colonna Identità appena generata nella tabella figlio, mentre si inserisce un nuovo record nella tabella padre. –

+0

Kohler: Per favore dimmi come fare, quando imposterò 'inversr =" true "'. –

+0

Ora dovresti vedere che ... Ho aggiornato la mia risposta. Ovviamente, l'entità figlia deve avere un riferimento a Parent. Controlla questo http://stackoverflow.com/a/30005490/1679310 per TUTTI I DETTAGLI –