【发布时间】:2016-12-22 12:45:52
【问题描述】:
我正在尝试使用 NHibernate 进行批量更新,但它没有进行批量更新,而是对所有行进行单独写入。我必须向 db 写入大约 10k 行。
using (var session = GetSessionFactory().OpenStatelessSession())
{
session.SetBatchSize(100);
using (var tx = session.BeginTransaction())
{
foreach (var pincode in list)
{
session.Update(pincode);
}
tx.Commit();
}
}
我尝试使用session.SetBatchSize(100); 将批量大小设置为 100,但这无济于事。还尝试使用cfg.SetProperty("adonet.batch_size", "100"); 设置批量大小,但这也无济于事。
我正在使用 GUID 主键,因此我不明白批量更新失败的原因。这正是here 解释的解决方案。但它不适合我。
注意我在所有实体上都映射了乐观并发的版本字段。这会是没有批量更新的罪魁祸首吗??
编辑
我尝试使用有状态会话,但这也没有帮助
//example 2
using (var session = GetSessionFactory().OpenSession())
{
session.SetBatchSize(100);
session.FlushMode = FlushMode.Commit;
foreach (var pincode in list)
{
session.Update(pincode);
}
session.Flush();
}
//example 3
using (var session = GetSessionFactory().OpenSession())
{
session.SetBatchSize(100);
using (var tx = session.BeginTransaction())
{
foreach (var pincode in list)
{
session.Update(pincode);
}
tx.Commit();
}
}
example 2 出于某种原因导致了两次往返。
编辑
经过进一步研究我发现,每个 session.Update 实际上都是在更新数据库
using (var session = SessionManager.GetStatelessSession())
{
session.SetBatchSize(100);
foreach (var record in list)
{
session.Update(record);
}
}
我怎样才能避免这种情况。
编辑
也尝试过刷新模式,但这也无济于事
using (var session = SessionManager.GetNewSession())
{
session.FlushMode = FlushMode.Never;
session.SetBatchSize(100);
session.BeginTransaction();
foreach (var pincode in list)
{
session.SaveOrUpdate(pincode);
}
session.Flush();
session.Transaction.Commit();
}
编辑 4
即使低于一个也不起作用,因为我正在获取同一会话中的所有实体并仅在该会话中更新和保存它们...
using (var session = SessionManager.GetSessionFactory().OpenSession())
{
session.SetBatchSize(100);
session.FlushMode = FlushMode.Commit;
session.Transaction.Begin();
var list = session.QueryOver<Pincode>().Take(1000).List();
list.ForEach(x => x.Area = "Abcd" + DateTime.Now.ToString("HHmmssfff"));
foreach (var pincode in list) session.SaveOrUpdate(pincode);
session.Flush();
session.Transaction.Commit();
}
【问题讨论】:
-
如果您的“pincode”是代理,您不需要调用
session.Update(pincode);如果是这样,如果您更改实体并调用session.Flush();,会发生什么? -
不,这些不是代理,这些对象是在另一个无状态会话中从数据库中获取的,应用了一些业务逻辑,然后批量保存...
-
在这种情况下,请参阅下面奥斯卡的回答。
-
但即使有状态会话也是如此,请参阅示例 2、示例 3 和最近的编辑...批量更新没有任何效果
-
据我所知,如果您的实体是从不同的会话中获取的,那么您仍然是无状态的。尝试使用相同的有状态会话获取、更改实体和提交。看看这是否有效。
标签: nhibernate