0

我有一个在 NHibernate 3.0 中使用 Linq to NHibernate 的 asp.net Web 应用程序。

在一个函数中,我需要从一个包含 20 列的 1000 万条记录的表中获取大约 20000 条记录。

我正在使用 Session.QueryOver<>() 方法来获取记录。

功能代码为:

public IList<BatchDetails> GetBatchRecordsOnBatchId_BatchSize(int batchId,int stratingRowdId,int batchSize)
    {
        // If the stratingRowdId will be 0 than frist count of the Batch Records equivlent to the batchSize will be return

        //If the batchSize will be 0 than all the Batch Records starting from the RowId equivlent to the stratingRowdId will be return

        // If both the stratingRowdId & batchSize are 0 than all the BatchReocrds for the BatchId will be return



        if (batchId <= 0)
        {

            throw new ArgumentException();
        }
        using (var session = _sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                try
                {
                    //Get Batch data from the Database for the BatchId
                    var batchData = from batchRecords in session.QueryOver<BatchDetails>()
                                        .Where(x => x.BatchId == batchId)
                                        .List().Skip(stratingRowdId).Take(batchSize)
                                    select batchRecords
                        ;

                    transaction.Commit();
                    return batchData.ToList();
                }
                catch (ArgumentException ex)
                {
                    if (transaction != null) transaction.Rollback();


                    throw;
                }
                catch (Exception exception)
                {
                    if (transaction != null) transaction.Rollback();

                    throw;
                }
                finally
                {
                    session.Flush();
                }
            }

        }
    }

此代码一直有效,直到表有 2 条 lac 记录。

但是在表中添加 10 条 lac 记录后,此方法会抛出错误:

NHibernate.Util.ADOExceptionReporter| 引发了“System.OutOfMemoryException”类型的异常。

NHibernate.Util.ADOExceptionReporter| 引发了“System.OutOfMemoryException”类型的异常。

NHibernate.Util.ADOExceptionReporter| 引发了“System.OutOfMemoryException”类型的异常。

PaymentCurrency 作为 Payment19_2_0_,this_.PaymentDate 作为 Payment20_2_0_,this_.TransactionId 作为 Transac21_2_0_,this_.BatchId 作为 BatchId2_0_ FROM TIOTestDB.dbo.BatchDetails this_WHERE this_.BatchId = ? ] 位置参数:#0>3 [SQL: SELECT this_.RefereId as Referenc1_2_0_, this_.AccNumber as AccountN2_2_0_, this_.AcStatus as AccountS3_2_0_, this_.AcType as AccountT4_2_0_, this_.AccSubType as AccountS5_2_0_, this_.AccountDescription as AccountD6_2_0_, this_. ActivationDate as Activati7_2_0_, this_.CombinedBilling as Combined8_2_0_, this_.PlanAmount as PlanAmount2_0_, this_.PlanCode as PlanCode2_0_, this_.CustomerName as Custome11_2_0_, this_.Email as Custome12_2_0_, this_.Phone as Custome13_2_0_, this_.Address as Custome14_2_0 Custome15_2_0_,this_.State 为 Custome16_2_0_,this_.ZipCode 为 Custome17_2_0_,this_。

当我在 foreach() 迭代中执行此函数时,虽然查询执行 1 或 2 次并检索数据,但之后它会引发 Out of memory 异常。

作为一名经验丰富的 NHibernate 开发人员,我可以理解我需要重组 LINQ 查询以优化其性能。

我也在互联网上搜索过,但我无法获得太多信息。

尽早答复将不胜感激。

4

1 回答 1

3

首先,您的查询:

from batchRecords in session.QueryOver<BatchDetails>()
    .Where(x => x.BatchId == batchId)
    .List().Skip(stratingRowdId).Take(batchSize)
select batchRecords

可以简化为:

session.QueryOver<BatchDetails>()
    .Where(x => x.BatchId == batchId)
    .List().Skip(stratingRowdId).Take(batchSize)

它的行为将完全相同。from您所做的所有select有效的工作就是.Select(x => x)在查询末尾添加。

现在,你的问题是你打电话List()太早了。所做的是List()将查询的所有结果检索到内存中。如果您在那之后使用 LINQ 方法(就像您使用Skip()and一样Take()),它们将在内存中执行,这不是您想要的。

你应该做的是移动List()到查询的末尾:

session.QueryOver<BatchDetails>()
    .Where(x => x.BatchId == batchId)
    .Skip(stratingRowdId).Take(batchSize)
    .List()

这样,两者都Skip()Take()被转换为 SQL,这意味着您不会将所有数据检索到内存中,而只会检索您实际需要的数据。这应该可以解决您的 OOM。

于 2012-06-06T12:58:00.267 回答