Click here to Skip to main content
Click here to Skip to main content

On-demand loading of images from a database

, 16 May 2012
Rate this:
Please Sign up or sign in to vote.
Loading an image from a database isn't difficult, but it can waste time. If you are loading a large list of Images (or even thumbnails) from a DB but not using them immediately, then it can take some considerable time. Why not load them on demand instead?

Introduction

If you have a database which contains images - even if they are thumbnails - then loading them all on startup can take serious amount of time. For example, a recent application had a Picture class, with an Id, a Description, a thumbnail image, and a location for the full image all stored in a database. On startup, I needed to load the Pictures from the DB, so I could tie them together with the other classes. With around 1000 100x100 pixel jpg thumbnails in the DB, it was taking 13 to 15 seconds to load them all at startup - a silly amount of time.

So, instead, I changed it to on demand loading - which means that the time to load the image (from file or database) is deferred until the image itself is actually needed. Since this is generally as a result of user actions, we are then talking in terms of human reaction speeds, and 1000th of 15 seconds (plus the extra overhead of a DB connection setup) doesn't make any difference, people just don't notice the delay.

Using the code

It's pretty easy to do. Assuming your Picture class is written properly, you already have a Image property for the thumbnail:

public Image Thumbnail {get; private set;}

All you have to do is replace the auto-implemented backing field with a private version, and move the database access code into the property:

/// <summary>
/// Base of the Thumbnail property - this allows the full image to only be loaded on demand.
/// </summary>
private Image thumbnail = null;

/// <summary>
/// Thumbnail for the image
/// </summary>
public Image Thumbnail 
{
    get
    {
        if (thumbnail == null)
        {
            // Not loaded yet - load on demand
            using (SqlConnection con = new SqlConnection(GenericData.DBConnection))
            {
                con.Open();
                using (SqlCommand cmd = new SqlCommand("SELECT Thumbnail FROM Images WHERE Id=@ID", con))
                {
                    cmd.Parameters.AddWithValue("@ID", Id);
                    SqlDataReader r = cmd.ExecuteReader();
                    if (r.Read())
                    {
                        MemoryStream ms = new MemoryStream((byte[])r["Thumbnail"]);
                        thumbnail = GenericData.GetImage(ms);
                    }
                }
            }
        }
        return thumbnail;
    }
    private set
    {
        thumbnail = value;
    }
}

The GetImage method just creates an image from a Stream without requiring the stream to be open for the lifetime of the Image: 

/// <summary>
/// Get an Image without locking the file.
/// </summary>
/// <remarks>
/// Image.FromFile and Image.FromStream have problems in that the first
/// locks the file until the Image is Disposed, and the latter requires
/// the stream to be open and available until the Image is Disposed, which
/// effectively locks the file as well.
/// This doesn't, because it uses a copy of the image.
/// </remarks>
/// <param name="stream"></param>
/// <returns></returns>
public static Image GetImage(Stream stream)
{
    Image img;
    using (Image temp = Image.FromStream(stream))
    {
        img = new Bitmap(temp);
    }
    return img;
} 

Points of Interest

This is something I do quite often, I just wish I'd remember to do it in the first place each time...

History

Original version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

OriginalGriff
CEO
Wales Wales
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word "the".
Invented the portable cat-flap.
Currently, has not died yet. Or has he?
Follow on   Google+

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 16 May 2012
Article Copyright 2012 by OriginalGriff
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid