2009-01-29 110 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); 
相關問題