【问题标题】:Cache and SqlCacheDependency (ASP.NET MVC)缓存和 SqlCacheDependency (ASP.NET MVC)
【发布时间】:2014-12-12 00:40:55
【问题描述】:

我们需要返回记录的子集,为此我们使用以下命令:

using (SqlCommand command = new SqlCommand(
                    "SELECT ID, Name, Flag, IsDefault FROM (SELECT ROW_NUMBER() OVER (ORDER BY @OrderBy DESC) as Row, ID, Name, Flag, IsDefault FROM dbo.Languages) results WHERE Row BETWEEN ((@Page - 1) * @ItemsPerPage + 1) AND (@Page * @ItemsPerPage)",
                    connection))

我设置了一个这样声明的 SqlCacheDependency:

SqlCacheDependency cacheDependency = new SqlCacheDependency(command);

但是在我运行 command.ExecuteReader() 指令后,SqlCacheDependency 对象的 hasChanged 基本属性变为 true,尽管我没有以任何方式更改查询结果!并且,正因为如此,这个查询的结果不会保存在缓存中。

HttpRuntime.Cache.Insert( cacheKey, list, cacheDependency, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(AppConfiguration.CacheExpiration.VeryLowActivity));

是因为该命令有 2 个 SELECT 语句吗?是 ROW_NUMBER() 吗?如果是,有没有其他方法可以对结果进行分页?

请帮忙!经过太多小时,一点点将不胜感激!谢谢

【问题讨论】:

    标签: caching dependencies sqlcachedependency cache-dependency


    【解决方案1】:

    遇到同样的问题并在没有任何帮助的情况下在线找到相同的答案,我正在重新搜索分析器的 xml 无效订阅响应。

    我在 msdn 支持网站上找到了一个示例,该示例的代码顺序略有不同。当我尝试它时,我意识到了问题 - 在创建命令对象和缓存依赖对象之前不要打开连接对象。这是您必须遵循的顺序,一切都会好起来的:

    1. 确保启用通知 (SqlCahceDependencyAdmin) 并首先运行 SqlDependency.Start
    2. 创建连接对象
    3. 创建命令对象并分配命令文本、类型和连接对象(构造函数、设置属性或使用 CreateCommand 的任意组合)。
    4. 创建 sql 缓存依赖对象
    5. 打开连接对象
    6. 执行查询
    7. 使用依赖项将项目添加到缓存。

    如果您遵循此顺序,并遵循您的 select 语句中的所有其他要求,则没有任何权限问题,这将起作用!

    我认为这个问题与 .NET 框架如何管理连接有关,特别是设置了哪些设置。我尝试在我的 sql 命令测试中覆盖它,但它从未奏效。这只是一个猜测 - 我所知道的是更改顺序立即解决了问题。

    我能够从以下到 msdn 帖子中拼凑起来。

    这篇文章是无效订阅的更常见原因之一,并展示了 .Net 客户端如何设置与通知所需的属性相反的属性。

    https://social.msdn.microsoft.com/Forums/en-US/cf3853f3-0ea1-41b9-987e-9922e5766066/changing-default-set-options-forced-by-net?forum=adodotnetdataproviders

    那么这篇文章来自一个和我一样的用户,他将他的代码简化为最简单的格式。我原来的 Code Pattern 和他的很相似。

    https://social.technet.microsoft.com/Forums/windows/en-US/5a29d49b-8c2c-4fe8-b8de-d632a3f60f68/subscriptions-always-invalid-usual-suspects-checked-no-joy?forum=sqlservicebroker

    然后我发现这篇文章,也是一个非常简单的问题减少,只有他是一个简单的问题 - 需要 2 个表的部分名称。在他的情况下,这个建议解决了这个问题。查看他的代码后,我注意到主要区别是等待打开连接对象,直到创建命令对象和依赖对象之后。我唯一的假设是在幕后(我还没有启动反射器来检查,所以只是一个假设)连接对象的打开方式不同,或者事件和命令的顺序发生不同,因为这种关联。

    https://social.msdn.microsoft.com/Forums/sqlserver/en-US/bc9ca094-a989-4403-82c6-7f608ed462ce/sql-server-not-creating-subscription-for-simple-select-query-when-using-sqlcachedependency?forum=sqlservicebroker

    我希望这可以帮助遇到类似问题的其他人。

    【讨论】:

    • 我开始意识到,虽然这可能会提供价值,但这只是达到目的的一种手段,企业从未明确要求它(显然)。有更简单的方法来实现可扩展性。这听起来太敏感了,因为没有具体或至少明确定义的奇怪行为可能会在版本之间发生变化,但很高兴知道有人找到了解决方案。
    【解决方案2】:

    只是猜测,但可能是因为您的 SELECT 语句没有 ORDER BY 子句吗?

    如果您未指定显式排序,则查询可以在每次运行时以任意顺序返回结果。可能这导致SqlCacheDependency 对象认为结果发生了变化。

    尝试添加ORDER BY 子句:

    SELECT ID, Name, Flag, IsDefault
    FROM
    (
        SELECT ROW_NUMBER() OVER (ORDER BY @OrderBy DESC) AS Row,
            ID, Name, Flag, IsDefault
        FROM dbo.Languages
    ) AS results
    WHERE Row BETWEEN ((@Page - 1) * @ItemsPerPage + 1) AND (@Page * @ItemsPerPage)
    ORDER BY Row
    

    【讨论】:

    • 谢谢,但它不起作用,因为结果已经被订购......我仍然尝试了,不幸的是我的期望是正确的。 1分尝试虽然:)
    【解决方案3】:

    我不是 SqlCacheDependency 方面的专家,事实上,我在寻找我自己的问题的答案时发现了这个问题!但是,我相信您的 SqlCacheDependency 不起作用的原因是因为您的 SQL 包含嵌套的子查询。

    查看文档,其中列出了您可以/不能在 SQL 中使用的内容:Creating a Query for Notification

    "....语句不得包含子查询、外连接或自连接....."

    我还从 Redgate 的一个人那里找到了一些宝贵的故障排除信息:Using and Monitoring SQL 2005 Query Notification,它帮助我解决了我自己的问题:通过使用 Sql Profiler 跟踪他建议的 QN 事件,我能够发现我的连接使用不正确'SET ARITHABORT OFF' 选项,导致我的通知失败。

    【讨论】:

    • 是的,这绝对是真的,我已经得出了这个结论。这些天来,SqlCacheDependency 对于大多数查询仍然无用,因为正如我们在第一个链接的“支持的 SELECT 语句”中看到的那样,限制太多了!有一个解决方法,但需要更多的工作。请勿设置缓存依赖关系,并且在编辑或删除选择的结果时,请使用缓存键删除缓存对象。如果您的应用程序做得好,它肯定会起作用。
    猜你喜欢
    • 2013-07-22
    • 1970-01-01
    • 2013-06-28
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多