假设我们有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();
}
}
}
编辑:我忘了提及我正在进行交易。
答案 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