Подтвердить что ты не робот

Исключено исключение типа "System.OutOfMemoryException". Зачем?

У меня есть динамический запрос, который возвращает около 590 000 записей. Он запускается успешно в первый раз, но если я запустил его снова, я продолжаю получать System.OutOfMemoryException. Каковы некоторые причины этого?

Ошибка здесь:

  public static DataSet GetDataSet(string databaseName,string
                                   storedProcedureName,params object[] parameters)
    {
        //Creates blank dataset
        DataSet ds = null;

        try
        {
            //Creates database
            Database db = DatabaseFactory.CreateDatabase(databaseName);
            //Creates command to execute
            DbCommand dbCommand = db.GetStoredProcCommand(storedProcedureName);
            dbCommand.CommandTimeout = COMMAND_TIMEOUT;
            //Returns the list of SQL parameters associated with that stored proecdure
            db.DiscoverParameters(dbCommand);

            int i = 1;
            //Loop through the list of parameters and set the values
            foreach (object parameter in parameters)
            {
                dbCommand.Parameters[i++].Value = parameter;
            }
            //Retrieve dataset and set to ds
            ds = db.ExecuteDataSet(dbCommand);
        }
            //Check for exceptions
        catch (SqlException sqle)
        {
            throw sqle;
        }
        catch (Exception e)
        {
            throw e; // Error is thrown here.
        }
        //Returns dataset
        return ds;
    }

Вот код, который запускается при нажатии кнопки:

protected void btnSearchSBIDatabase_Click(object sender, EventArgs e)
{

        LicenseSearch ls = new LicenseSearch();

        DataTable dtSearchResults = new DataTable();

        dtSearchResults = ls.Search();

        Session["dtSearchResults"] = dtSearchResults;

        Response.Redirect("~/FCCSearch/SearchResults.aspx");
        }
        else
            lblResults.Visible = true;
    }
4b9b3361

Ответ 1

Он запускается успешно в первый раз, но если я запустил его снова, я продолжаю получать Исключение System.OutOfMemoryException. Какие это некоторые причины, по которым это может быть происходит?

Независимо от того, что говорили другие, ошибка не имеет никакого отношения к тому, чтобы забыть распоряжаться своим DBCommand или DBConnection, и вы не будете исправлять свою ошибку, удалив любой из них.

Ошибка имеет все, что связано с вашим набором данных, который содержит около 600 000 строк данных. По-видимому, ваш набор данных потребляет более 50% доступной памяти на вашем компьютере. Понятно, что у вас закончится память, когда вы вернете другой набор данных того же размера, прежде чем первый будет собран мусором. Просто как это.

Вы можете устранить эту проблему несколькими способами:

  • Рассмотрите возможность возврата меньшего количества записей. Я лично не могу представить себе время, когда возвращение 600K записей когда-либо было полезным для пользователя. Чтобы свести к минимуму возвращаемые записи, попробуйте:

    • Ограничение вашего запроса на первые 1000 записей. Если из запроса возвращено более 1000 результатов, сообщите об этом пользователю, чтобы сузить результаты поиска.

    • Если ваши пользователи действительно настаивают на том, чтобы сразу увидеть это много данных, попробуйте выполнить подкачку данных. Помните: Google никогда не показывает вам всего 22 бай-диона результатов поиска сразу, он показывает вам примерно 20 записей за раз. Google, вероятно, не сохраняет сразу все 22 баджона в памяти, вероятно, он считает, что более эффективно использовать память для создания своей новой базы данных.

  • Если вам просто нужно перебирать данные и вам не нужен произвольный доступ, попробуйте вместо этого вернуть datareader. Datareader загружает только одну запись в память за раз.

Если ни одна из них не является опцией, вам необходимо заставить .NET освободить память, используемую набором данных, прежде чем вызывать свой метод с помощью одного из этих методов:

  • Удалите все ссылки на старый набор данных. Все, что держится за обновление вашего набора данных, не позволит ему восстановить память.

  • Если вы не можете удалить все ссылки на свой набор данных, очистите все строки из набора данных и любые объекты, привязанные к этим строкам. Это удаляет ссылки на datarows и позволяет им съедаться сборщиком мусора.

Я не верю, что вам нужно вызвать GC.Collect(), чтобы заставить цикл gen. Это не просто идея назвать GC.Collect(), потому что достаточное давление памяти вызовет .NET, который вызовет сборщик мусора самостоятельно.

Примечание: вызов Dispose в вашем наборе данных не освобождает память и не вызывает сборщик мусора, а также не удаляет ссылку на ваш набор данных. Dispose используется для очистки неуправляемых ресурсов, но DataSet не имеет неуправляемых ресурсов. Он только реализует IDispoable, потому что он присущ MarshalByValueComponent, поэтому метод Dispose в наборе данных практически бесполезен.

Ответ 2

Возможно, вы не избавляетесь от предыдущих классов соединения/результата от предыдущего запуска, что означает, что они все еще висят в памяти.

Ответ 3

Вы, очевидно, не распоряжаетесь вещами.

Рассмотрим команду "use", когда вы временно используете объекты, реализующие IDisposable.

Ответ 4

попытайтесь как можно больше разорвать ваши большие данные, потому что я уже сталкивался с количеством проблем такого типа. В которой у меня выше 10 лакских записей с 15 столбцами.

Ответ 5

Где это происходит?

Я согласен с тем, что ваша проблема, вероятно, в том, что ваш набор данных из 600 000 строк, вероятно, слишком велик. Я вижу, что вы добавляете его в сеанс. Если вы используете состояние сеанса Sql, ему также придется сериализовать эти данные.

Даже если вы правильно распоряжаетесь своими объектами, у вас всегда будет как минимум 2 копии этого набора данных в памяти, если вы запускаете его дважды, один раз в сеансе, один раз в процедурный код. Это никогда не будет масштабироваться в веб-приложении.

Выполняет ли математика 600 000 строк даже с шагом 1-128 бит в строке, что дает 9,6 мегабайт (600 тыс. * 128/8) только данных, не говоря уже о служебных данных набора данных.

Обрезайте результаты.