Зависимость SQLCACHED от представлений и процедур

#asp.net #sql-server-2008 #caching #sqlcachedependency #broker

#asp.net #sql-server-2008 #кэширование #зависимость sqlcached от #брокер

Вопрос:

Я хочу использовать SqlCacheDependency с представлениями и процедурами.

Я использую Linq to Sql.

Код, который я использую в настоящее время, допустим, только если вы используете одну таблицу:

 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;
   }
}
  

Теперь я хочу реализовать зависимость sqlcached для представления (нескольких таблиц).

Я пытаюсь использовать этот запрос

 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);
  

Но этот запрос не работает, потому что кэш не становится недействительным, даже если я изменяю базовые таблицы.

Я слишком долго гуглил, но не могу найти код, который работал бы для представлений и процедур или нескольких таблиц.

Ответ №1:

Вам не нужно выдавать отдельный запрос в стиле SqlCommand при использовании уведомлений на основе таблиц — ваш ExecuteNonQuery и связанный с ним код избыточны. Просто добавьте результаты LINQ в созданную вами AggregateCacheDependency.

Вы уверены, что полностью включили уведомления об изменениях на основе таблиц? Существует таблица, некоторые триггеры и хранимая процедура, которые необходимо создать в БД, плюс некоторый код на сервере для запуска периодического опроса. Обязательно подождите достаточно долго, пока произойдет опрос, прежде чем объявлять, что срок действия кэша не истек.

Вы также можете самостоятельно просмотреть содержимое таблицы изменений, чтобы увидеть, улавливаются ли изменения на стороне базы данных:

ВЫБЕРИТЕ * ИЗ [dbo].[AspNet_SqlCacheTablesForChangeNotification]

Если изменения из одной таблицы работают, вы можете попробовать использовать SqlCacheDependency.Вместо этого создайте outputdependency (зависимость от строки), чтобы немного упростить ваш код. Аргумент представляет собой список из одной или нескольких таблиц вида «DdName:имя_таблицы;DbName:имя_таблицы». Имя базы данных берется из web.config.

Сказав все это, я должен также указать, что уведомления об изменениях на основе таблиц устарели, и новый код должен использовать уведомления Service Broker вместо этого. Да, их можно настроить для работы с LINQ.