2009-01-29 16 views
33

Para mantener mis pruebas de integración independientes, elimino todos los datos antiguos e inserto nuevos datos de prueba antes de cada prueba. ¿Hay una forma mejor de hacer esto que simplemente consultar todas las entidades y eliminarlas una por una?¿La mejor manera de borrar todas las filas en una tabla usando NHibernate?

He considerado escribir un proceso almacenado que ejecuta "eliminar de tablename;" para cada tabla que se va a borrar. Eso debería ser un poco más rápido, pero sería bueno hacerlo sin hacer consultas SQL o llamar a SP a través de NH.

Estoy usando vainilla NHibernate y Linq para NHibernate. Creo que Castle Active Record tiene algo así como Foo.DeleteAll(), pero no quiero usar Active Record para este proyecto.

¿Alguna idea?

Gracias/Erik

ACTUALIZACIÓN:

Dado que esta cuestión se le preguntó y respondió, se ha avanzado por el equipo de NHibernate. Como explica Ayende en this blog post, ahora puede ejecutar consultas DML directamente, sin que NHibernate tenga que buscar entidades.

Para eliminar objetos que podría hacer así todo Foo:

using (ISession session = ...) 
using (ITransaction transaction = session.BeginTransaction()) 
{ 
    session.CreateQuery("delete Foo f").ExecuteUpdate(); 

    transaction.Commit(); 
} 

Esta consulta generaría el siguiente SQL:

delete from Foo 

el que nada a ser significativamente más rápido que ir a buscar las entidades primera y luego eliminándolos. Tenga cuidado, ya que consultas como estas no afectan el nivel 1 de la caché.

+2

Si está utilizando SQL Server, es MUCHO más eficiente ejecutar 'TRUNCATE TABLE foo;' ya que es una operación mínimamente registrada. Ejecutando 'DELETE FROM foo;' registra todas las eliminaciones para fines de recuperación; en tablas grandes esto requiere un disco/tiempo significativo. –

+3

TRUNCATE TABLE casi nunca está disponible cuando hay claves foráneas involucradas. –

Respuesta

32

En el TearDown de mis unittests, que en su mayoría hacen esto:

using(ISession s = ...) 
{ 
    s.Delete ("from Object o"); 
    s.Flush(); 
} 

Esto debería eliminar todas las entidades. Si desea eliminar todas las instancias de una entidad específica, se puede hacer esto:

using(ISession s = ....) 
{ 
    s.Delete ("from MyEntityName e"); 
    s.Flush(); 
} 

Offcourse, hay un inconveniente de este método, y es que NHibernate primero buscará las entidades antes de eliminarlos.

+0

Oh, me había perdido totalmente que puede pasar una consulta a session.Delete(). ¡Gracias! –

+7

BTW: es mortalmente lento en tablas grandes –

+0

INdeed, ese es el inconveniente que mencioné. –

10

utilizo Fluido Nhibernate atributos así que modificar el código un poco para no incondicionales nombres de tabla

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(); 
     } 
    } 
} 

uso

CleanUpTable<Person>(sessionFactory); 
+0

He decidido no editar esta pregunta porque "hardcore" realmente suena mucho mejor que "hardcode", aunque es lo último que probablemente haya querido decir. –

1

Con NHibernate 5.0 ahora se puede simplemente hacer:

session.Query<Foo>().Delete(); 

Documentación:

// 
    // 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); 
Cuestiones relacionadas