views:

62

answers:

1

I have been trying to get SqlCacheDependency working. I think I have everything set up correctly, but when I update the table, the item in the Cache isn't invalidated.

Can you look at my code and see if I am missing anything?

I enabled the Service Broker for the Sandbox database. I have placed the following code in the Global.asax file. I also restart IIS to make sure it is called.

void Application_Start(object sender, EventArgs e) {
   SqlDependency.Start(ConfigurationManager.ConnectionStrings["SandboxConnectionString"].ConnectionString);
}

I have placed this entry in the web.config file:

<system.web>
    <caching>
        <sqlCacheDependency enabled="true" pollTime="10000">
            <databases>
                <add name="Sandbox" connectionStringName="SandboxConnectionString"/>
            </databases>
        </sqlCacheDependency>
    </caching>
</system.web>

I call this code to put the item into the cache:

protected void CacheDataSetButton_Click(object sender, EventArgs e) {
    using (SqlConnection sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["SandboxConnectionString"].ConnectionString)) {
        using (SqlCommand sqlCommand = new SqlCommand("SELECT PetID, Name, Breed, Age, Sex, Fixed, Microchipped FROM dbo.Pets", sqlConnection)) {
            using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand)) {
                DataSet petsDataSet = new DataSet();
                sqlDataAdapter.Fill(petsDataSet, "Pets");

                SqlCacheDependency petsSqlCacheDependency = new SqlCacheDependency(sqlCommand);
                Cache.Insert("Pets", petsDataSet, petsSqlCacheDependency, DateTime.Now.AddSeconds(10), Cache.NoSlidingExpiration);
            }           
        }
    }
}

Then I bind the GridView with this code:

protected void BindGridViewButton_Click(object sender, EventArgs e) {
    if (Cache["Pets"] != null) {
        GridView1.DataSource = Cache["Pets"] as DataSet;
        GridView1.DataBind();
    }
}

Between attempts to DataBind the GridView, I change the table's values expecting it to invalidate the Cache["Pets"] item, but it seems to stay in the Cache indefinitely.

+1  A: 

You must attach the SqlCacheDependency to the SqlCommand before you execute the command:

using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand)) {
    DataSet petsDataSet = new DataSet();
    SqlCacheDependency petsSqlCacheDependency = 
        new SqlCacheDependency(sqlCommand);
    sqlDataAdapter.Fill(petsDataSet, "Pets");
    Cache.Insert("Pets", petsDataSet, petsSqlCacheDependency,
        DateTime.Now.AddSeconds(10), Cache.NoSlidingExpiration);
} 
Remus Rusanu
I changed my code to the above, but it still remains in the cache. It's also interesting to me that it isn't removed from the cache after 10 seconds, which I would expect.
Jason
Check if the subscription is created (`select * from sys.dm_qn_subscriptions`) and check if the notification isn't stuck (`select * from <dbname>.sys.transmission_queue`)
Remus Rusanu
Thank you for your help Remus. When I first queried those tables I saw three errors in the sys.transmission_queue "An exception occurred while enqueueing a message in the target queue. Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission." I followed some posts to straighten that out by assigning ownership to SA. See next comment...
Jason
Now when I add the dataset to the queue and query the sys.dm_qn_subscriptions table there is one entry. After I update the table, the row is removed.
Jason
'dbo' is mapped to an invalid login, you probably copied the database from another instance. run `alter authorization on database::<dbname> to [sa]`
Remus Rusanu
D'oh, u already did that. Now the notification is set up and the query gets notified. Cache should be invalidated if ASP does it's part of the deal. See here to understand how this behemoth works: http://rusanu.com/2006/06/17/the-mysterious-notification/
Remus Rusanu
Damnit all, it was a stupid mistake after all >:( You'll notice that when I bind the GridVeiw I only take into account the possibility of it being not null. If it *is* null, the binding won't happen of course but I don't clear the GridView. So while I thought I was rebinding the GridView it was actually just showing the old data =OGoing to mark it as the answer because you led me to the permissions issue that needed to be resolved. Thank you so much for your time Remus.
Jason
Glad it helped. I couldn't notice the mistake in binding since my understanding of things ASPish stops way before binding comes into picture :)
Remus Rusanu