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?

有帮助吗?

解决方案

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top