Il modo migliore per eliminare tutte le righe in una tabella utilizzando NHibernate?
-
20-08-2019 - |
Domanda
Per mantenere i miei test di integrazione indipendenti rimuovo tutti i vecchi dati e inserisco nuovi dati di test prima di ogni test. Esiste un modo migliore per farlo che semplicemente interrogare tutte le entità ed eliminarle una per una?
Ho pensato di scrivere un proc memorizzato che esegue " elimina da tablename ; " per ogni tabella che deve essere cancellata. Dovrebbe essere un po 'più veloce, ma sarebbe bello farlo senza fare query SQL o chiamare SP tramite NH.
Sto usando NHibernate vaniglia e Linq per NHibernate. Credo che Castle Active Record abbia qualcosa come Foo.DeleteAll (), ma non voglio usare Active Record per questo progetto.
Qualche idea?
Grazie / Erik
UPDATE:
Da quando questa domanda è stata posta e risposta, il team di NHibernate ha fatto progressi. Come spiega Ayende in questo post sul blog , ora puoi eseguire query DML direttamente, senza che NHibernate debba recuperare alcuna entità.
Per cancellare tutti gli oggetti Foo potresti fare così:
using (ISession session = ...)
using (ITransaction transaction = session.BeginTransaction())
{
session.CreateQuery("delete Foo f").ExecuteUpdate();
transaction.Commit();
}
Questa query genererebbe il seguente SQL:
delete from Foo
che dovrebbe essere significativamente più veloce che recuperare prima le entità e poi cancellarle. Fai attenzione, poiché query come queste non influiscono sulla cache di livello 1.
Soluzione
Nel TearDown dei miei UnitTest, lo faccio principalmente:
using( ISession s = ... )
{
s.Delete ("from Object o");
s.Flush();
}
Questo dovrebbe eliminare tutte le entità. Se desideri eliminare tutte le istanze di una specifica entità, puoi farlo:
using( ISession s = .... )
{
s.Delete ("from MyEntityName e");
s.Flush();
}
Offcourse, c'è un inconveniente con questo metodo, e cioè che NHibernate prenderà prima le entità prima di cancellarle.
Altri suggerimenti
Uso gli attributi Fluent Nhibernate, quindi modifico un po 'il codice in modo da non creare nomi di tabella hardcore
private static void CleanUpTable<T>(ISessionFactory sessionFactory)
{
var metadata = sessionFactory.GetClassMetadata(typeof(T)) as NHibernate.Persister.Entity.AbstractEntityPersister;
string table = metadata.TableName;
using (ISession session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
string deleteAll = string.Format("DELETE FROM \"{0}\"", table);
session.CreateSQLQuery(deleteAll).ExecuteUpdate();
transaction.Commit();
}
}
}
utilizzo
CleanUpTable<Person>(sessionFactory);
Con NHibernate 5.0 ora puoi semplicemente fare:
session.Query<Foo>().Delete();
Documentazione:
//
// Summary:
// Delete all entities selected by the specified query. The delete operation is
// performed in the database without reading the entities out of it.
//
// Parameters:
// source:
// The query matching the entities to delete.
//
// Type parameters:
// TSource:
// The type of the elements of source.
//
// Returns:
// The number of deleted entities.
public static int Delete<TSource>(this IQueryable<TSource> source);