【问题标题】:Processing large number of records with NHibernate使用 NHibernate 处理大量记录
【发布时间】:2011-04-16 20:26:07
【问题描述】:

使用 NHibernate 加载集合和更新所有项目的最佳方法是什么。当前代码加载 50 个对象并在其自己的事务中处理每个对象(如果 1 个失败,则其他都可以)。

NH Profiler 说每个会话有太多的 sql 查询。

毕竟,你觉得这段代码怎么样?

using (var session = sessionFactory.OpenSession())
        {
            var myCollection =
                (from obj in session.Query<MyObject>()
                 select obj).Take(50);

            foreach (var item in myCollection)
            {
                using (var tx = session.BeginTransaction())
                {
                    try
                    {
                        //  Do some stuff...
                        session.Update(item);
                        tx.Commit();
                    }
                    catch (Exception)
                    {
                        tx.Rollback();
                    }
                }
            }
        }

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    来自NHibernate: Streaming large result sets

    NHibernate 旨在用于 OLTP 系统,因此,它通常是 在我们想要加载的情况下使用 相对较少的数据来自 数据库,使用它并保存它 背部。对于报告方案,有 是更好的选择,通常(和 在你问之前,任何报告包 会做。适合工作的工具等)。

    但在某些情况下你想 在报告中使用 NHibernate 尽管如此。也许是因为 报告要求不是 足以证明去一个单独的 工具,或者因为你想用什么 你已经知道了。在那些情况下 你容易遇到问题的地方, 因为你违反了假设 在建造时制作的 NHibernate。

    using (IStatelessSession s = sessionFactory.OpenStatelessSession())
    {
        var books = new ActionableList<Book>(book => Console.WriteLine(book.Name));
        s.CreateQuery("from Book")
            .List(books);
    
    }
    

    无状态会话,不像 正常的 NHibernate 会话,不 跟踪加载的对象,因此 这里的代码和数据阅读器代码是 本质上是一样的。

    基本上,使用无状态会话和批处理。另请阅读:NHibernate Perf Tricks

    【讨论】:

    • 根据最初的问题,如果不同时将所有记录加载到内存中,您将如何 /update/ 每条记录?
    • @pettys 在这种情况下,我会使用纯 HQL 和 ExecuteUpdate() -> docs.jboss.org/hibernate/core/3.3/reference/en/html/…
    • 这是有道理的。对于琐碎的 CRUD 操作,纯 HQL 或 SQL 是一个很好的解决方案。对于非平凡的域聚合,HQL 或 SQL 将绕过域逻辑。示例:发生了一个事件,其中 500 位客户刚刚赢得了“首选客户!”地位。当我调用 Customer.MakePreferred() 时,会有域事件发送祝贺电子邮件并对系统中的其他值进行面向计算的调整。我意识到我在这里手工制作了一个最坏的情况 - 只是看看它可能会带来什么其他想法。
    【解决方案2】:

    你有多少查询?也许您正遭受select N+1 问题的困扰,因为您在“做事”部分中的每个对象上都添加了惰性属性。尝试在第一个查询中加入对象上急切地加载您需要的所有部分。

    【讨论】:

    • 没有select+1的问题。我只是觉得我做错了事。
    猜你喜欢
    • 2012-10-29
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多