2011-11-14 19 views
3

我想使用SqlCacheDependency与视图和过程。我正在使用Linq to Sql对视图和过程的SqlCacheDependency

我目前使用的代码才有效,如果你使用的是单表:

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

现在我要实现的视图(多表)中的SqlCacheDependency。

我尝试使用此查询

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

但此查询不工作,因为缓存不失效,即使我改变底层表。

我googled它太久了,但我找不到一个适用于视图和过程或多个表的代码。

回答

1

当您使用基于表格的通知时,您不需要发出单独的SqlCommand样式查询 - 您的ExecuteNonQuery和相关代码是多余的。只需将LINQ结果与您构建的AggregateCacheDependency一起添加即可。

您确定您已完全启用基于表格的更改通知吗?有一个表格,一些触发器和一个需要在数据库中创建的存储过程,以及服务器上的一些代码来触发定期轮询。在声明缓存未过期之前,请务必等待足够长的时间才能进行轮询。

您也可以看看变化表自己的内容,看是否改变正在上拿起DB方:

SELECT * FROM [DBO] [AspNet_SqlCacheTablesForChangeNotification]

如果来自单个表的更改正在工作,您可以尝试使用SqlCacheDependency.CreateOutputDependency(string depend)来简化代码。参数是“DdName:TableName; DbName:TableName”形式的一个或多个表的列表。 DbName来自web.config。

说了这么多,我还应该指出,基于表格的更改通知已被弃用,新代码应该使用Service Broker通知。是的,他们可以与LINQ一起工作。