NHibernate:如何删除一组对象?

时间:2011-12-27 13:23:38

标签: nhibernate

假设我们有100个User类型的对象,每个用户都有一对一的引用。 NHibernate配置中的批处理大小设置为50.因此,如果我们删除所有100个对象,NHibernate将触发200个与DB的连接。我希望在每个连接中使用4个连接以及50个查询来删除它们。下面的代码是我的批量插入方法的复制/粘贴,它按预期工作:

public void BatchDelete(IEnumerable<T> entitiesToDelete)
    {
        int batchSzie = Session.GetSessionImplementation().Batcher.BatchSize;
        int batchedInsertsCount = 0;
        foreach (var entity in entitiesToDelete)
        {
            batchedInsertsCount++;
            Session.Delete(entity);
            if (batchedInsertsCount % batchSzie == 0)
            {
                Session.Flush();
                Session.Clear();
            }
        }
    }
编辑:我忘了提及我正在进行交易。

3 个答案:

答案 0 :(得分:4)

            Session.Flush();
            Session.Clear();

通常表示您做错了什么,开始添加交易并删除:

if (batchedInsertsCount % batchSzie == 0)

另一种方法可以是带有删除和查询的查询:

            // fill batch with id list of items you want to delete
            _session.CreateQuery(String.Format("DELETE  FROM TABLENAME WHERE Id IN (:idsList)", _domainObject.Name))
                    .SetParameterList("idsList", batch.ToArray())
                    .ExecuteUpdate();

确保检查2100 max ids,这是您可以为sqlserver提供的参数的最大值。

答案 1 :(得分:3)

你过度复杂了。

只需配置所需的批量大小,执行所有必需的Session.Delete调用,然后提交您的交易。

NHibernate将执行entitiesToDelete.Count() / batch size次查询。

以下是代码示例:

using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    foreach (var foo in session.Query<Foo>())
        session.Delete(foo);
    tx.Commit();
}

示例配置:

var config = new Configuration();
config.SessionFactory()
      .Integrate.Using<MsSql2008Dialect>().Connected.Using("...")
      .BatchingQueries.Each(10);

(我正在设置批量大小的显式值,但NH 3.2默认为20 IIRC)

如果存在级联集合,则需要确保数据库处理删除。

您需要将FK定义为ON DELETE CASCADE,并让NH知道:

<class name="Foo">
  <id ...>...</id>
  <bag name="Bars" inverse="true" cascade="all">
    <key column="FooId" on-delete="cascade" />
    <one-to-many class="Bar" />
  </bag>
</class>
<class name="Bar">
  <id ...>...</id>
  <many-to-one name="Foo" column="FooId" />
</class>

在这种情况下,Foo的{​​{1}}集合已保留到Bars列。

答案 2 :(得分:0)

首先,您没有为会话设置批处理大小(session.BatchSize()),因此它将使用默认设置或创建sessionfactory时配置的内容。但更重要的是,不支持批量删除。即使你正确设置session.BatchSize()它也没有效果(至少使用NHibernate 3.2和SQL Server 2008)。 Ayende has a blog post that shows how to solve the problem