سؤال

I want to use SqlCacheDependency with the views and procedures.

I am using Linq to Sql.

The code i am currently using is valid only if you are using a Single Table:

public static List<T> LinqCache<T>(this System.Linq.IQueryable<T> q, System.Data.Linq.DataContext dc, string CacheId)
{
   try
   {
      List<T> objCache = (List<T>)System.Web.HttpRuntime.Cache.Get(CacheId);

      if (objCache == null)
      {
         /////////No cache... implement new SqlCacheDependeny//////////
         //1. Get connstring from DataContext
         string connStr = dc.Connection.ConnectionString;

         var c = System.Web.Caching.SqlCacheDependencyAdmin.GetTablesEnabledForNotifications(connStr);

         //2. Get SqlCommand from DataContext and the LinqQuery
         string sqlCmd = dc.GetCommand(q).CommandText;

         //3. Create Conn to use in SqlCacheDependency
         using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr))
         {
            conn.Open();
            //4. Create Command to use in SqlCacheDependency
            using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sqlCmd, conn))
            {
               //5.0 Add all parameters provided by the Linq Query
               foreach (System.Data.Common.DbParameter dbp in dc.GetCommand(q).Parameters)
               {
                  cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter(dbp.ParameterName, dbp.Value));
               }

               //5.1 Enable DB for Notifications... Only needed once per DB...
               System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(connStr);

               //5.2 Get ElementType for the query
               string NotificationTable = q.ElementType.Name;

               //5.3 Enable the elementtype for notification (if not done!)
               if (!System.Web.Caching.SqlCacheDependencyAdmin.GetTablesEnabledForNotifications(connStr).Contains(NotificationTable))
                  System.Web.Caching.SqlCacheDependencyAdmin.EnableTableForNotifications(connStr, NotificationTable);

               //6. Create SqlCacheDependency
               System.Web.Caching.SqlCacheDependency sqldep = new System.Web.Caching.SqlCacheDependency(cmd);
               // - removed 090506 - 7. Refresh the LinqQuery from DB so that we will not use the current Linq cache
               // - removed 090506 - dc.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, q);
               //8. Execute SqlCacheDepency query...
               cmd.ExecuteNonQuery();
               //9. Execute LINQ-query to have something to cache...
               objCache = q.ToList();
               //10. Cache the result but use the already created objectCache. Or else the Linq-query will be executed once more...
               System.Web.HttpRuntime.Cache.Insert(CacheId, objCache, sqldep);
            }
         }
      }
      //Return the created (or cached) List
      return objCache;
   }
   catch (Exception ex)
   {
     throw ex;
   }
}

Now i want to implement the sqlcachedependency for the view (multiple tables).

I try to use this query

System.Web.Caching.SqlCacheDependency
dep1 = new System.Web.Caching.SqlCacheDependency(cmd1),
dep2 = new System.Web.Caching.SqlCacheDependency(cmd2);

System.Web.Caching.AggregateCacheDependency aggDep = new System.Web.Caching.AggregateCacheDependency();
aggDep.Add(dep1, dep2);

dc.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, q);
cmd.ExecuteNonQuery();
objCache = q.ToList();
System.Web.HttpRuntime.Cache.Insert(CacheId, objCache, aggDep);

But this query does not work because the cache does not becomes invalid even though I change the underlying tables.

I googled it for too long but i cannot find a code that worked for views and procedures or multiple tables.

هل كانت مفيدة؟

المحلول

You should not need to issue a separate SqlCommand-style query when using table based notifications -- your ExecuteNonQuery and related code are redundant. Just add the LINQ results with the AggregateCacheDependency that you've built.

Are you sure that you've fully enabled table-based change notifications? There is a table, some triggers and a stored procedure that need to be created in the DB, plus some code on the server to trigger the periodic polling. Be sure to wait long enough for the polling to happen before declaring that the cache is not being expired.

You can also look at the contents of the changes table yourself, to see if the change is being picked up on the DB side:

SELECT * FROM [dbo].[AspNet_SqlCacheTablesForChangeNotification]

If changes from a single table are working, you might try using SqlCacheDependency.CreateOutputDependency(string depend) instead, to simplify your code a bit. The argument is a list of one or more tables, of the form "DdName:TableName;DbName:TableName". The DbName comes from in web.config.

Having said all that, I should also point out that table-based change notifications are deprecated, and new code should use Service Broker notifications instead. Yes, they can be made to work with LINQ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top