SqlCacheDependency для представлений и процедур - PullRequest
3 голосов
/ 14 ноября 2011

Я хочу использовать 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;
   }
}

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

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

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 Ответ

1 голос
/ 03 декабря 2011

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

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

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

SELECT * FROM [dbo]. [AspNet_SqlCacheTablesForChangeNotification]

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

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

...