2009-01-29 108 views
33

为了保持独立的集成测试,我删除所有旧数据并在每次测试前插入新的测试数据。有没有比单纯查询所有实体并逐个删除它们更好的方法?使用NHibernate删除表中所有行的最佳方法?

我曾考虑编写一个存储过程,该过程运行“从表中删除;”对于每个要清除的表。这应该快得多,但是如果不通过SQL查询或通过NH调用SP,将会很好。

我使用香草NHibernate和Linq到NHibernate。我相信Castle Active Record有类似Foo.DeleteAll()的功能,但我不想在此项目中使用Active Record。

任何想法?

感谢/埃里克

UPDATE:

因为这个问题被提出和回答,进展一直由NHibernate的团队做。正如Ayende在this blog post中解释的那样,您现在可以直接执行DML查询,而无需NHibernate获取任何实体。

要删除所有的Foo对象,你可以这样做:

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

    transaction.Commit(); 
} 

的查询方法生成的SQL语句:

delete from Foo 

其中奥特是显著快于第一,然后取实体删除它们。但要小心,因为这样的查询不会影响1级缓存。

+2

如果您使用的是SQL Server,执行`TRUNCATE TABLE foo;`会更有效,因为这是一个最小化日志操作。执行`DELETE FROM foo;`记录所有删除以进行恢复;在大型表上这需要大量的磁盘/时间。 – 2009-06-22 18:20:14

+3

当涉及外键时,TRUNCATE TABLE几乎不可用。 – 2011-11-10 16:11:55

回答

32

在我的单元测试的拆机,我主要是做这个:

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

这应该删除所有实体。 如果你想删除某个特定实体的所有实例,你可以这样做:

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

Offcourse,有使用这种方法的缺点,那就是NHibernate的会先删除前获取的实体。

+0

哦,我完全错过了,你可以传递一个查询session.Delete()。谢谢! – 2009-01-29 09:22:24

10

我用流利的NHibernate的属性,所以我修改代码一点,以不铁杆表名

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

使用

CleanUpTable<Person>(sessionFactory); 
1

与NHibernate 5.0,你现在可以简单地这样做:

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

文档:

// 
    // 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); 
相关问题