nhibernate:批量执行更新

时间:2014-10-20 17:57:00

标签: nhibernate

我正在尝试使用NHibernate进行批量更新,但它没有进行批量更新,它为所有行执行单独写入。我必须写大约10k行到db。

        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实际上都在更新db

        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();
        }

3 个答案:

答案 0 :(得分:2)

您正在使用无状态会话。由于无状态会话没有状态,因此以后无法记住任何事情。因此,更新立即执行。

答案 1 :(得分:2)

nhibernate 不批量版本化实体这就是我的问题。

您无法批量处理版本实体,唯一要做的就是使实体不进行版本控制。

答案 2 :(得分:1)

请注意:

  • 批次在Sql Server Profiler 中不可见。不要依赖于此。
  • 使用身份(或原生)ID生成器插入时,NH会关闭ado.net批量大小。

附加说明:

  • 确保您没有查询每个已更改的实体,因为它会在查询之前刷新。
  • 您可能不应该调用session.Update。在最好的情况下,它什么都不做。在最坏的情况下,它确实会更新,因此会破坏批处理。

在会话中有很多对象时,不要忘记关注刷新和刷新时间。有时刷新比更新更耗时。在提交之前,当您调用flush和查询之前,NH会刷新,除非您将其关闭或使用无状态会话。确保只冲洗一次。