Caching the results from LinqDataSource

Posted Monday, August 13, 2007 3:24 PM by pwelter34

I wanted to be able to cache the results of a query from the LinqDataSource that was used in multiple places on the page.  I whipped up this little class to do the work of caching for me.  The class, LinqCacheDataSource, handles the Selecting and Selected events.  The Selected handler inserts the result of the query into cache.  The Selecting handler gets the result from the cache.  If it doesn't find the result, the query runs as normal.  The caching will only work for selecting data.  It works great for dropdowns and other fairly static data.

The Code ...

/// <summary>

/// A LinqDataSource that provides caching for Linq queries.

/// </summary>

public class LinqCacheDataSource : LinqDataSource

{

    /// <summary>

    /// Initializes a new instance of the <see cref="LinqCacheDataSource"/> class.

    /// </summary>

    public LinqCacheDataSource()

        : base()

    {

        this.Selecting += new EventHandler<LinqDataSourceSelectEventArgs>(OnSelecting);

        this.Selected += new EventHandler<LinqDataSourceStatusEventArgs>(OnSelected);

    }

 

    private void OnSelecting(object sender, LinqDataSourceSelectEventArgs e)

    {

        if (!EnableCache)

            return;

 

        string key = GetKey();

        object source = Context.Cache[key];

        if (source == null)

            return;

 

        Debug.WriteLine("Cache Hit: " + key);

        e.Result = source;

    }

 

    private void OnSelected(object sender, LinqDataSourceStatusEventArgs e)

    {

        if (!EnableCache)

            return;

 

        if (e.Exception != null || e.Result == null)

            return;

 

        string key = GetKey();

        object source = Context.Cache[key];

        if (source != null)

            return;

 

        Debug.WriteLine("Cache Insert: " + key);

        Context.Cache.Insert(key, e.Result, null,

            DateTime.Now.AddSeconds(Duration), Cache.NoSlidingExpiration);

    }

 

    private string GetKey()

    {

        StringBuilder sb = new StringBuilder();

        sb.Append(this.ContextTypeName);

        sb.Append(" from ");

        sb.Append(this.TableName);

 

        if (!string.IsNullOrEmpty(this.Select))

        {

            sb.Append(" select ");

            sb.Append(this.Select);

        }

        if (!string.IsNullOrEmpty(this.Where))

        {

            sb.Append(" where ");

            sb.Append(this.Where);

        }

        if (!string.IsNullOrEmpty(this.OrderBy))

        {

            sb.Append(" OrderBy ");

            sb.Append(this.OrderBy);

        }

        return sb.ToString();

    }

 

    /// <summary>

    /// Gets or sets a value indicating whether query caching is enabled.

    /// </summary>

    [DefaultValue(true)]

    [Category("Cache")]

    [Description("Enable caching the linq query result.")]

    public bool EnableCache

    {

        get

        {

            object result = this.ViewState["EnableCache"];

            if (result != null)

                return (bool)result;

 

            return true;

        }

        set

        {

            this.ViewState["EnableCache"] = value;

        }

    }

 

    /// <summary>

    /// Gets or sets the time, in seconds, that the query is cached.

    /// </summary>

    [DefaultValue(30)]

    [Category("Cache")]

    [Description("The time, in seconds, that the query is cached.")]

    public int Duration

    {

        get

        {

            object result = this.ViewState["Duration"];

            if (result != null)

                return (int)result;

 

            return 30;

        }

        set

        {

            this.ViewState["Duration"] = value;

        }

    }

}

 

Filed under: ,

Comments

# re: Caching the results from LinqDataSource

Sunday, February 17, 2008 10:58 PM by Jon

Thanks for sharing!

# re: Caching the results from LinqDataSource

Thursday, May 01, 2008 12:44 PM by boflynn

How do you use this declaratively?

i.e. how can I go <asp:LinqCacheDataSource ...

on my aspx page?

# re: Caching the results from LinqDataSource

Friday, July 11, 2008 5:35 PM by Jim

Hi Peter,

I've tried using this in vb, and am having trouble inheriting from  linqdatasource on the following line:

Public Class LinqDataSourceWCaching

   Inherits LinqDataSource

I get an error, 'type linqdatasource is not defined.

I've imported the following namespaces (among others)

Any ideas on where I'm going wrong?

Imports System.Data

Imports System.Data.Linq

Imports System.Data.Linq.Mapping

Imports System.Linq

Imports System.Linq.Expressions

# re: Caching the results from LinqDataSource

Friday, July 11, 2008 6:16 PM by Jim

I figured out that last problem.  I had to reference system.web.extensions in my project.

Thanks,

Jim

Leave a Comment

(required) 
(required) 
(optional)
(required)