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.

È stato utile?

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top