Click here to Skip to main content
16,018,318 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have been assigned a “legacy” .Net 3.5 C# “desktop” application. I have limited C#/.Net 3.5 experience. The users of the “desktop” application want the load of a specific Windows form to have better performance. On load, the form reads into a “DataTable” roughly 3,300 five column records from an Oracle database using a “DbDataAdapter”. I want to "cache" these records the first time the form gets loaded and read from the cache on any subsequent form loads.

I have been researching ways of implementing a C# .Net 3.5 "cache" for some time but, most solutions refer to ASP.NET or the “MemoryCache” class from the .Net 4.0 Framework.

Can someone please suggest a method of implementing a C# .Net 3.5 "cache" that uses the .Net 3.5 Framework in a “desktop” application?

What I have tried:

I tried using the implementation of a "cache" in the article Cache<t>: A threadsafe, Simple, Efficient, Generic In-memory Cache but get errors I believe are a result of using the .Net 3.5 Framework.
Posted
Updated 2-Sep-20 1:00am
Comments
Rob Philpott 12-Sep-24 13:27pm    
Is this still an issue for you? 3300x5 columns isn't really that much data (at all) unless the columns are massive.

Caching really isn't going to help much with that problem.

First, loading all the records doesn't scale well, even if you cache the result. You're just transferring more and more data all in one block.

The problem you have is that you're loading 3,300 records into a DataGrid. That takes forever.

The real solution is to either filter the records down so you're not loading thousands of records, or paging, where you're only fetching 20 to 30 records to fill the grid and you load more as the user pages down through the grid.
 
Share this answer
 
Recommendation is to never get your hands dirty for such performance-oriented parts of your application unless you have a solid experience/understanding. Oh, before I start the answer, I should suggest that migrating the code to .NET Framework 4 and onwards (.NET Core and .NET Core vNext) should be the preferable route to take here. .NET Framework 3 and older systems are no longer supported and you are more likely to stumble upon such issues.

If you are interested in using the in-memory caching solution, please refer to modern caching systems such as Redis/Memcached to make the best possible use of caching resources and the system.

Redis[^]

Note: please verify if the server/client libraries for the caching systems provide support for .NET Framework 3.5, which is highly unlikely.

If you are still looking for something more custom, then try checking this thread on SO[^]; it gives an idea of how a cache system looks like. One thing to note is that caching is more than just storing, caching is about removing elements when no longer needed in the cache to maintain a manageable size, etc.
 
Share this answer
 
C#
using System.Data;

namespace MyNamespace
{
    public sealed class MyData
    {
        private static readonly MyData instance = new MyData();
        private DataTable data;

        public DataTable Data
        {
            get
            {
                return data;
            }
        }
            
        static MyData()
        {
        }

        private MyData()
        {
            // Populate your data here

            data = new DataTable();
            data.Columns.Add("ID", typeof(int));
            data.Columns.Add("Name", typeof(string));

            data.Rows.Add(1, "John");
            data.Rows.Add(1, "David");
        }

        public static MyData Instance
        {
            get
            {
                return instance;
            }
        }
    }
}


Usage

C#
private void Form1_Load(object sender, EventArgs e)
{
    DataTable dt = MyData.Instance.Data;

    System.Diagnostics.Debug.WriteLine(dt.Rows[0][0].ToString() + " " + dt.Rows[0][1].ToString());
}
 
Share this answer
 
public class CustomMemoryCachePolicy
{
    public CustomMemoryCachePolicy(DateTime expiration)
    {
        Expiration = expiration;
    }

    public DateTime Expiration { get; set; }
}


public class CustomMemoryCache
{
    private Dictionary<string, object> cacheObjects;
    private Dictionary<string, CustomMemoryCachePolicy> cacheObjectsPolicy;

    public CustomMemoryCache()
    {
        cacheObjects = new Dictionary<string, object>();
        cacheObjectsPolicy = new Dictionary<string, CustomMemoryCachePolicy>();
    }

    public object Get(string key)
    {
        lock (cacheObjects)
        {
            ApplyPolicies(key);
            object target;
            cacheObjects.TryGetValue(key, out target);
            return target ?? null;
        }
    }

    public void Set(string key, object value, CustomMemoryCachePolicy policy = null)
    {
        lock (cacheObjects)
        {
            ApplyPolicies(key);
            cacheObjects.Add(key, value);
            cacheObjectsPolicy.Add(key, policy);
        }
    }

    public bool Contains(string key)
    {
        ApplyPolicies(key);
        return cacheObjects.ContainsKey(key);
    }

    private void ApplyPolicies(string key)
    {
        CustomMemoryCachePolicy targetPolicy;
        cacheObjectsPolicy.TryGetValue(key, out targetPolicy);

        if(targetPolicy != null)
        {
            if(DateTime.Now > targetPolicy.Expiration)
            {
                Remove(key);
            }
        }
    }

    public void Remove(string key)
    {
        lock (cacheObjects)
        {
            if (cacheObjects.ContainsKey(key))
                cacheObjects.Remove(key);

            if (cacheObjectsPolicy.ContainsKey(key))
                cacheObjectsPolicy.Remove(key);
        }
    }
}
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900