37

为了让我的集成测试保持独立,我删除了所有旧数据并在每次测试之前插入新的测试数据。有没有比简单地查询所有实体并一个一个删除它们更好的方法呢?

我考虑过编写一个运行“从表名中删除 ”的存储过程 对于要清除的每个表。这应该会快一些,但最好不要执行 SQL 查询或通过 NH 调用 SP。

我正在使用香草 NHibernate 和 Linq to NHibernate。我相信 Castle Active Record 有类似 Foo.DeleteAll() 的东西,但我不想在这个项目中使用 Active Record。

有任何想法吗?

谢谢/埃里克

更新:

自从提出并回答了这个问题以来,NHibernate 团队已经取得了进展。正如 Ayende 在这篇博文中解释的那样,您现在可以直接执行 DML 查询,而 NHibernate 不必获取任何实体。

要删除所有 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

在我的单元测试的拆解中,我主要这样做:

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

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

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 回答
8

使用 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);
于 2017-11-01T11:58:21.597 回答