简体   繁体   中英

SqlCacheDependency/SqlDependency and columns

I am using the following code to cache with dependency on change of "People" table's, "Name" column. However, in a row if some other column such as Address column changes then also dependency fires and purges the cache. (ASP.NET 4.0 with SQL Server 2008.)

public string GetTheVals()
{
    string vals = HttpContext.Current.Cache["TheCacheKey__X"] as string;
    if (vals == null)
    {
        con = GetConnection();
        SqlCommand cmd = new SqlCommand(@"
SELECT Name
FROM dbo.People
", con);            
        con.Open();
        SqlCacheDependency sqlDependency = new SqlCacheDependency(cmd);
        SqlDataReader rdr = null;

        StringBuilder builder = new StringBuilder("");
        rdr = cmd.ExecuteReader();
        while (rdr.Read())
        {
            builder.Append(rdr[0].ToString());
        }
        vals = builder.ToString();

        HttpContext.Current.Cache.Insert("TheCacheKey__X", vals, sqlDependency, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));
        CloseConnection(con);
    }
    return vals;
}

Why does it fire when a value of a column which is not in the query of the command changed although it is said to be fired when results changed?

You can also assign a delegate to the OnChange event, which will fire when the results change for an associated command.

http://msdn.microsoft.com/en-us/library/62xk7953.aspx

It is also required to state columns explicitly so we understand that it will filter out other columns of the table and will not fire.

  • So, why does it require to explicitly state column names?
  • Is it just for making developers aware of what they are doing (such as when using inner joins) and avoid creating dependencies that will cause worst performance?

The projected columns in the SELECT statement must be explicitly stated , and table names must be qualified with two-part names. Notice that this means that all tables referenced in the statement must be in the same database.

The statement may not use the asterisk (*) or table_name.* syntax to specify columns.

The statement must not contain subqueries, outer joins, or self-joins.

http://msdn.microsoft.com/en-us/library/ms181122(v=sql.105).aspx

According to MS help , however:

SQL Server sends a query notification for a subscription when one of the following events occurs:

  • Rows contained in the query results may have changed.

  • The subscription expires.

  • The server restarts.

  • The query notification subscription could not be created (for example, the SELECT statement does not conform to the requirements specified in Creating a Query for Notification.

  • The server is heavily loaded.

  • Objects that the subscription depends on are dropped or modified.

Notice that SQL Server may produce a query notification in response to events that do not change the data , or in response to a change that does not actually affect the results of the query. For example, when an UPDATE statement changes one of the rows returned by the query, the notification may fire even if the update to the row did not change the columns in the query results .

As i work with SQL Cache dependency I've noticed many points you should take in consideration.

One of them you cant cache a table depending on column name, if you would like to see your cache tables open AspNet_SqlCacheTablesForChangeNotification in your database.

SELECT TOP 1000 [tableName] ,[notificationCreated] ,[changeId] FROM [dbo].[AspNet_SqlCacheTablesForChangeNotification]

You will notice when the changeId will be fired, on Update, Insert or Delete and this will trigger the cache to be flushed.

Very important to always check your queries in the commandnotification, many queries are not supported as you said above.

Regards and hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM