Come si può eliminare un'entità in nhibernate avendo solo il suo ID e tipo?
-
19-09-2019 - |
Domanda
Mi chiedo come si possa eliminare un'entità avente solo il suo ID e tipo (come nella mappatura) utilizzando NHibernate 2.1?
Soluzione
Se utilizzi il caricamento lento, Load crea solo un proxy.
session.Delete(session.Load(type, id));
Con NH 2.1 puoi usare HQL.Non sono sicuro di come sia effettivamente, ma qualcosa del genere: tieni presente che questo è soggetto a SQL injection - se possibile, utilizzare invece query parametrizzate con SetParameter()
session.Delete(string.Format("from {0} where id = {1}", type, id));
Modificare:
Per Load, non è necessario conoscere il nome della colonna Id.
Se hai bisogno di saperlo, puoi ottenerlo tramite i metadati NH:
sessionFactory.GetClassMetadata(type).IdentifierPropertyName
Un'altra modifica.
session.Delete()
sta istanziando l'entità
Quando si utilizza session.Delete(), NH carica comunque l'entità.All'inizio non mi piaceva.Poi ho capito i vantaggi.Se l'entità fa parte di una struttura complessa che utilizza ereditarietà, raccolte o riferimenti "qualsiasi", in realtà è più efficiente.
Ad esempio, se class A
E B
entrambi ereditano da Base
, non tenta di eliminare i dati nella tabella B
quando l'entità effettiva è di tipo A
.Ciò non sarebbe possibile senza caricare l'oggetto reale.Ciò è particolarmente importante quando sono presenti molti tipi ereditati, ciascuno composto anche da molte tabelle aggiuntive.
La stessa situazione si verifica quando si dispone di una raccolta di Base
s, che sono tutte istanze di A
.Quando si carica la collezione in memoria, NH sa che non è necessario rimuoverne alcuna B
-cose.
Se l'entità A
ha una collezione di B
s, che contiene C
s (e così via), non tenta di eliminarne nessuno C
s quando la raccolta di B
s è vuoto.Questo è possibile solo leggendo la raccolta.Ciò è particolarmente importante quando C è complesso di per sé, aggregando ancora più tabelle e così via.
Quanto più complessa e dinamica è la struttura, tanto più efficiente è caricare i dati effettivi invece di eliminarli "alla cieca".
Le eliminazioni HQL presentano insidie
HQL elimina per non caricare i dati in memoria.Ma le eliminazioni HQL non sono così intelligenti.Fondamentalmente traducono il nome dell'entità nel nome della tabella corrispondente e lo rimuovono dal database.Inoltre, elimina alcuni dati di raccolta aggregati.
Nelle strutture semplici, questo può funzionare bene ed efficiente.Nelle strutture complesse, non tutto viene cancellato, il che porta a violazioni dei vincoli o "perdite di memoria del database".
Conclusione
Ho anche provato a ottimizzare la cancellazione con NH.Nella maggior parte dei casi ho rinunciato, perché NH è ancora più intelligente, "funziona e basta" e di solito è abbastanza veloce.Uno degli algoritmi di eliminazione più complessi che ho scritto è l'analisi delle definizioni di mappatura NH e la creazione di istruzioni di eliminazione da esse.E, nessuna sorpresa, non è possibile senza leggere i dati dal database prima di eliminarli.(L'ho appena ridotto per caricare solo le chiavi primarie.)