37

統合テストを独立した状態に保つために、古いデータをすべて削除し、各テストの前に新しいテスト データを挿入します。すべてのエンティティを単純にクエリして 1 つずつ削除するよりも、これを行うためのより良い方法はありますか?

「delete from tablename ;」を実行するストアド プロシージャを作成することを検討しました。クリアするテーブルごとに。これはかなり高速になるはずですが、SQL クエリを実行したり、NH を介して SP を呼び出したりせずに実行できると便利です。

私はバニラNHibernateとLinq to NHibernateを使用しています。Castle Active Record には Foo.DeleteAll() のようなものがあると思いますが、このプロジェクトでは Active Record を使用したくありません。

何か案は?

ありがとう/エリック

アップデート:

この質問が尋ねられて回答されて以来、NHibernate チームは進歩を遂げてきました。Ayende がこのブログ投稿で説明しているように、NHibernate がエンティティをフェッチしなくても、DML クエリを直接実行できるようになりました。

すべての Foo オブジェクトを削除するには、次のようにします。

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

    transaction.Commit();
}

このクエリは、次の SQL を生成します。

delete from Foo

最初にエンティティを取得してから削除するよりもはるかに高速です。ただし、このようなクエリはレベル 1 キャッシュには影響しないため、注意してください。

4

3 に答える 3

33

UnitTests の TearDown では、主にこれを行います。

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

これにより、すべてのエンティティが削除されます。特定の 1 つのエンティティのすべてのインスタンスを削除する場合は、次のようにします。

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

もちろん、この方法には欠点があります。それは、NHibernate がエンティティを削除する前にまずフェッチすることです。

于 2009-01-29T09:17:41.070 に答える
12

Fluent 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);
于 2013-05-31T15:46:34.710 に答える