Question

I am trying to get the new SqlChangeMonitor feature included in the System.Runtime.Caching namespace to work and am getting some unexpected results.

I have a simple console application setup as:

static void Main(string[] args)
{
    var cacher = new Cacher();

    cacher.Start();

    Console.WriteLine("Watching for changes...");

    while (true)
    {
        if (cacher.HasData)
        {
            Console.Write(".");
            Thread.Sleep(1000);
        }
        else
        {
            Console.WriteLine();
            Console.WriteLine("Cache EMPTY!");
            Console.ReadLine();
            cacher.Start();
        }
    }
}

The Cacher class is defined as:

public class Cacher
{
    private MemoryCache cache = new MemoryCache("test");

    public Boolean HasData
    {
        get { return cache.Contains("data"); }
    }

    public void Start()
    {
        var connectionString = "Data Source=.;Initial Catalog=CachingTest;Integrated Security=True";
        var list = new NameValueCollection();
        var policy = new CacheItemPolicy();

        SqlDependency.Start(connectionString);

        using (var connection = new SqlConnection(connectionString))
        {
            using (var command = new SqlCommand("SELECT * FROM dbo.Table_1", connection))
            {
                var dependency = new SqlDependency(command);

                connection.Open();

                var reader = command.ExecuteReader();

                while (reader.Read())
                {
                    list.Add(reader["Name"].ToString(), reader["Value"].ToString());
                }

                var monitor = new SqlChangeMonitor(dependency);

                policy.ChangeMonitors.Add(monitor);
            }

            cache.Add("data", list, policy);
        }
    }
}

When I run the code, I get the Waiting message and a single dot '.', the one second delay, then the "Cache Empty" message. This is repeated after I press a key to restart the loop.

What am I missing?

Was it helpful?

Solution

It turns out that my original problem was caused by using the asterisk (*) wildcard in the SELECT statement. As soon as I listed the column names, the cache started working properly.

I also wanted to receive notifications in code when the cache has been updated/cleared. The NotifyOnChanged method of the ChangeMonitor does not work as this is intended for internal use.

As it turns out, the CacheItemPolicy object has two callbacks: RemovedCallback and UpdateCallback that may be used for these purposes. Simply set these properties to methods in code and take the desired action.

Given the lack of documentation available on the SqlChangeMonitor, I hope this may be of assistance to anyone else running into these issues.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top