統合テストを独立させるために、すべての古いデータを削除し、各テストの前に新しいテストデータを挿入します。単にすべてのエンティティをクエリして1つずつ削除するよりも、これを行うためのより良い方法はありますか?
「deletefromtablename;」を実行するストアドプロシージャを作成することを検討しました。クリアするテーブルごとに。これはかなり高速になるはずですが、SQLクエリを実行したりNH経由でSPを呼び出したりせずに実行するとよいでしょう。
私はVanillaNHibernateとLinqをNHibernateに使用しています。 Castle Active RecordにはFoo.DeleteAll()のようなものがあると思いますが、このプロジェクトではActiveRecordを使用したくありません。
何か案は?
ありがとう/エリック
更新:
この質問に答えて以来、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のキャッシュに影響を与えないので注意してください。
UnitTestsのTearDownでは、主に次のことを行います。
using( ISession s = ... )
{
s.Delete ("from Object o");
s.Flush();
}
これにより、すべてのエンティティが削除されます。 1つの特定のエンティティのすべてのインスタンスを削除する場合は、次のようにします。
using( ISession s = .... )
{
s.Delete ("from MyEntityName e");
s.Flush();
}
もちろん、この方法には欠点があります。それは、NHibernateが最初にエンティティをフェッチしてから削除することです。
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);
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);