4

我正在使用以下代码缓存依赖于“人员”表的“名称”列的更改。但是,如果某个其他列(例如地址列)连续发生更改,则依赖项也会触发并清除缓存。(带有 SQL Server 2008 的 ASP.NET 4.0。)

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

为什么它会在不在命令查询中的列的值发生更改时触发,尽管据说它是在结果更改时触发的?

您还可以为 OnChange 事件分配一个委托,该事件将在关联命令的结果更改时触发。

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

还需要显式声明列,以便我们了解它将过滤掉表的其他列并且不会触发。

  • 那么,为什么需要显式声明列名呢?
  • 是否只是为了让开发人员意识到他们在做什么(例如在使用内部连接时)并避免创建会导致性能最差的依赖项?

SELECT 语句中的投影列必须明确声明,并且表名必须用两部分名称限定。请注意,这意味着语句中引用的所有表都必须在同一个数据库中。

该语句不能使用星号 (*) 或 table_name.* 语法来指定列。

该语句不得包含子查询、外部联接或自联接。

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

4

2 回答 2

3

但是,根据MS 帮助

当发生以下事件之一时,SQL Server 会发送订阅查询通知:

  • 查询结果中包含的行可能已更改。

  • 订阅到期。

  • 服务器重新启动。

  • 无法创建查询通知订阅(例如,SELECT 语句不符合为通知创建查询中指定的要求。

  • 服务器负载很重。

  • 订阅所依赖的对象被删除或修改。

请注意,SQL Server可能会生成查询通知以响应不更改数据的事件,或者响应实际上不影响查询结果的更改。例如,当 UPDATE 语句更改查询返回的行之一时,即使对该行的更新没有更改查询结果中的列,通知也可能触发

于 2012-10-25T08:16:27.093 回答
1

当我使用 SQL Cache 依赖项时,我注意到您应该考虑很多点。

如果您想查看缓存表在数据库中打开AspNet_SqlCacheTablesForChangeNotification ,其中之一您不能根据列名缓存表。

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

您会注意到 changeId 何时被触发,在更新、插入或删除时,这将触发缓存被刷新。

始终在命令通知中检查您的查询非常重要,正如您上面所说,许多查询不受支持。

问候并希望它有所帮助。

于 2012-10-25T08:24:55.037 回答