Как сохранить большую коллекцию nhibernate, не вызывая OutOfMemoryException - PullRequest
0 голосов
/ 15 июня 2010

Как сохранить большую коллекцию с помощью NHibernate, элементы которой превышают объем памяти, разрешенный для процесса?

Я пытаюсь сохранить объект Video с nhibernate, который имеет большое количество снимков экрана (код ниже).Каждый снимок экрана содержит байт [], поэтому после того, как nhibernate попытается сохранить около 10 000 записей одновременно, генерируется исключение OutOfMemoryException.Обычно я пытался бы прервать сохранение и очистить сессию после каждых 500 или около того записей, но в этом случае мне нужно сохранить коллекцию, потому что она автоматически сохраняет SortOrder и VideoId для меня (без скриншота, который должен знать, что онбыл частью видео).Каков наилучший подход с учетом моей ситуации?Есть ли способ разбить это сохранение, не заставляя Screenshot знать его родительское видео?

Для справки, вот код из простого примера, который я создал:

public class Video
{
    public long Id { get; set; }
    public string Name { get; set; }

    public Video()
    {
        Screenshots = new ArrayList();
    }

    public IList Screenshots { get; set; }
}

public class Screenshot
{
    public long Id { get; set; }
    public byte[] Data { get; set; }
}

И сопоставления:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SavingScreenshotsTrial"
                   namespace="SavingScreenshotsTrial"
                   default-access="property">
  <class name="Screenshot"
         lazy="false">
    <id name="Id"
        type="Int64">
      <generator class="hilo"/>
    </id>

    <property name="Data" column="Data" type="BinaryBlob" length="2147483647" not-null="true" />
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="SavingScreenshotsTrial"
                   namespace="SavingScreenshotsTrial" >
  <class name="Video"
         lazy="false"
         table="Video"
         discriminator-value="0"
         abstract="true">
    <id name="Id"
        type="Int64"
        access="property">
      <generator class="hilo"/>
    </id>
    <property name="Name" />
    <list name="Screenshots"
          cascade="all-delete-orphan"
          lazy="false">
      <key column="VideoId" />
      <index column="SortOrder" />
      <one-to-many class="Screenshot" />
    </list>
  </class>
</hibernate-mapping>

Когда я пытаюсь сохранить видео с 10000 скриншотами, оно вызывает исключение OutOfMemoryException.Вот код, который я использую:

        using (var session = CreateSession())
        {
            Video video = new Video();
            for (int i = 0; i < 10000; i++)
            {
                video.Screenshots.Add(new Screenshot() {Data = camera.TakeScreenshot(resolution)});
            }
            session.SaveOrUpdate(video);
        }

Ответы [ 3 ]

2 голосов
/ 15 июня 2010

По этой причине у нас, как правило, дочерняя сущность ссылается на родителя, а не наоборот.

0 голосов
/ 14 ноября 2018

Эта проблема решена в главе 13 документации nhibernate.

"Наивный подход к вставке 100 000 строк в базу данных с использованием NHibernate может выглядеть следующим образом:

using (ISession session = sessionFactory.OpenSession())
using (ITransaction tx = session.BeginTransaction())
{
for (int i = 0; i < 100000; i++)
{
Customer customer = new Customer(.....);
session.Save(customer);
}
tx.Commit();
}

Это может произойти с OutOfMemoryException где-то около 50 000-й строки [...] "

Чтобы возобновить ... решение состоит в том, чтобы работать с размером пакета и без кэша второго уровня, задав следующие свойства:

Размер партии:

adonet.batch_size 20

Кэш второго уровня:

cache.use_second_level_cache false

Должно быть достаточно, чтобы решить OutOfMemoryException.

Дополнительные данные в справочной документации: http://nhibernate.info/previous-doc/v5.0/single/nhibernate_reference.pdf

0 голосов
/ 30 января 2013

Создайте пользовательский тип, используя AbstractType и IParameterizedType, они находятся в пространстве имен NHibernate.Type. Используйте сеанс без сохранения состояния и укажите размер пакета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...