How to save a large nhibernate collection without causing OutOfMemoryException

Posted by Michael Hedgpeth on Stack Overflow See other posts from Stack Overflow or by Michael Hedgpeth
Published on 2010-06-14T23:46:47Z Indexed on 2010/06/14 23:52 UTC
Read the original article Hit count: 406

Filed under:
|

How do I save a large collection with NHibernate which has elements that surpass the amount of memory allowed for the process?

I am trying to save a Video object with nhibernate which has a large number of Screenshots (see below for code). Each Screenshot contains a byte[], so after nhibernate tries to save 10,000 or so records at once, an OutOfMemoryException is thrown. Normally I would try to break up the save and flush the session after every 500 or so records, but in this case, I need to save the collection because it automatically saves the SortOrder and VideoId for me (without the Screenshot having to know that it was a part of a Video). What is the best approach given my situation? Is there a way to break up this save without forcing the Screenshot to have knowledge of its parent Video?

For your reference, here is the code from the simple sample I created:

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

And mappings:

<?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>

When I try to save a Video with 10000 screenshots, it throws an OutOfMemoryException. Here is the code I'm using:

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

© Stack Overflow or respective owner

Related posts about c#

Related posts about nhibernate