Domanda

I have a wcf service which I make some database queries. And for not hammering the database I want to cache some of the queries. I searched and found that SqlDependency class and System.Runtime.Caching could be used for this purpose. Then I've found these articles link1, link2. I figured that 2nd article takes it on step ahead and updates the cache too. But whatever I do, I could not manage to get it working. Below there is my service code.

public class LocalDatabase : ILocalDatabase
{
    public LocalDatabase ()
    {
        SqlDependency.Start(connectionString);
        _cache = MemoryCache.Default;
    }

    public List<string> GetData ( string value )
    {
        if ( MemoryCache.Default["exceptions"] == null )
        {
            // Create a policy.
            var policy = new CacheItemPolicy();

            // Load data into Cache Item.
            var exceptions = new List<string>();

            using ( var connection = new SqlConnection(ConnectionString) )
            using ( var command = new SqlCommand("SELECT [Exception] FROM [myDb].[dbo].[ServiceException]", connection) )
            {
                var sqlDependency = new SqlDependency();
                sqlDependency.AddCommandDependency(command);
                connection.Open();

                using ( var result = command.ExecuteReader() )
                    while ( result.Read() )
                        exceptions.Add(result.GetString(0));

                var sqlMonitor = new SqlChangeMonitor(sqlDependency);

                policy.ChangeMonitors.Add(sqlMonitor);

                /// Events
                //sqlDependency.OnChange += sqlDep_OnChange;
                //policy.UpdateCallback = Exceptions_CacheUpdateCallback; 
            }

            // Set Cache Item into cache with the policy.
            MemoryCache.Default.Add("exceptions", exceptions, policy);
        }

        return MemoryCache.Default.Get("exceptions") as List<string>;
    }

    void sqlDep_OnChange ( object sender, SqlNotificationEventArgs e )
    {
        /// not firing this
    }

    void Exceptions_CacheUpdateCallback ( CacheEntryUpdateArguments args )
    {
        /// not firing this either
    }
}

In the first article, it doesn't even tied the events, but still claims it works, thus I removed the event handlers all together, but nothing changes. The problem is on first call to the service method it loads the cache from db, and the next calls gets their response from cache it is pretty good, but when a db change occurs either an insert or an update or a delete, it does not evict the cache, so it keeps giving the deprecated results. Then I have uncommented the event handlers, and those event got never fired either.

Edit: Btw, I have executed these two commands on sql server too.

ALTER DATABASE database_name SET TRUSTWORTHY ON WITH ROLLBACK IMMEDIATE
ALTER DATABASE database_name SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE

What I might be missin here?

Edit2: My other concern is as far as I know the default service behaviour of this is InstanceContextMode.PerCall. Will it affect this dependency concept? Or should I change the instance context mode too?

I can give more details if needed.

È stato utile?

Soluzione

Turned out I have constructed my sql query in a wrong format which violates the rules declared here. Below is the sample of my mistake and the correction of it.

My wrong query:

SELECT p.Id, d.Id
FROM [MyDb].[dbo].[Personnel] p, [MyDb].[dbo].[Department] d
WHERE p.DepartmentId = d.Id

The corrected version:

SELECT [dbo].[Personnel].Id, [dbo].[Department].Id
FROM [dbo].[Personnel] INNER JOIN [dbo].[Department]
  ON [dbo].[Personnel].DepartmentId = [dbo].[Department].Id
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top