在asp.net中缓存sql server数据,直到修改行为止

时间:2012-09-14 11:51:38

标签: asp.net sql-server-2008

我经常以以下形式运行查询:

select * from SomeTable where id=12345

页面后页我可能正在运行相同的查询,因为用户需要该行的值。通常我会获取一次并缓存它,但用户可以随时更改行,而其他用户也同时在SomeTable中进行更改,因此我无法对整个表进行缓存。我还有一个问题,即我们有一个用于Web服务器的集群,因此当缓存失效时,我无法在Web服务器上进行内部跟踪。

有没有办法检测到这一行发生了变化? SqlDependecyCache类可以在这里帮助单个行到多个Web服务器吗?是否有一些可以通知我的Web应用程序的触发器或其他范例?

我希望两全其美 - 网络服务器上的实时缓存更新,但我不想运行任何查询以查看该行是否已更改,因为我可以轻松地再次获取该行。

2 个答案:

答案 0 :(得分:3)

您需要的是启用SqlCacheDependency作为@RenusRusanu提及。

我有几个工作示例on my Github site,随时可以浏览 the code under my LearningProjects 第三方编辑

您需要先配置数据库才能使用SqlCacheDependency:

为了使用SQL依赖关系,我们需要在数据库中基本配置两件事:

  1. 创建包含表和存储过程的数据库基础结构,我们使用aspnet_regsql.exe进行配置,如下所示:

    /* For SQL Server authentication... */
    aspnet_regsql.exe -S server -U user -P password -d database -ed
    /* For Windows Authentication... */
    aspnet_regsql.exe -S server -E -d database -ed
    
  2. 创建轮询信息,包括指定要监控的表和触发该表以填充所需的基础架构表

        /* For SQL Server authentication... */
            aspnet_regsql.exe -S server
           -U user -P password -d database -t tableName -et
            /* For Windows Authentication... */
           aspnet_regsql.exe -S server
           -E -d database -t tableName -et
    
  3. 代码配置

            var s = new SqlCacheDependency("AdventureWorks", "Product");
    
            HttpContext.Current.Cache.Insert(
                "products", 
                h, 
                s, 
                Cache.NoAbsoluteExpiration, 
                Cache.NoSlidingExpiration);
    

    AdventureWorks名称是web.config文件中配置的sql依赖关系的名称

    <caching>
      <sqlCacheDependency enabled="true" pollTime="30000" >
        <databases>
          <add 
               name="AdventureWorks"
               connectionStringName="AdventureWorksPolling" />
        </databases>
      </sqlCacheDependency>
    </caching>
    

    可以在pollTime元素中配置<add ...,并覆盖全局polltime

    或者您可以依赖SqlDataSource控件

    为了在使用此控件时启用缓存,您需要将DataSourceMode属性设置为DataSet。在这种情况下,您不需要按照之前的说明配置数据库

    I just uploaded this example (full working example)

    ASPX

        <asp:SqlDataSource runat="server" ID="sds"
            ConnectionString="<%$ConnectionStrings:pubsConnectionString %>"
            CacheDuration="30"
            EnableCaching="true"
            SelectCommand="select * from jobs"
            DataSourceMode="DataSet"
            OnSelecting="sds_Selecting">
    
        </asp:SqlDataSource>
        <div>
            <asp:Literal runat="server" ID="msg" Mode="Encode"></asp:Literal>
        </div>
        <asp:GridView runat="server" DataSourceID="sds"></asp:GridView>
    

    编辑1

    为了在使用SqlCacheDependency时有选择地触发触发器,您需要更新手动生成的触发器。

    使用aspnet_regsql -t -et...命令配置表时,会将触发器添加到指定的表中。此触发器负责填充SqlCacheDependency对象使用的AspNet_SqlCacheTablesForChangeNotification表,以轮询数据库中的数据。

    触发器如下:

    ALTER TRIGGER [dbo].[jobs_AspNet_SqlCacheNotification_Trigger] ON [dbo].[jobs]
                       FOR INSERT, UPDATE, DELETE AS BEGIN
                       SET NOCOUNT ON
                       EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure N'jobs'
                       END
    

    您可以更新触发器,以便在您感兴趣的行更新时调用dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedureN'jobs'存储过程

    我不是SQL专家,但我认为很容易找到一种干净的方法来检测已经发生变化的行,例如google搜索我刚发现这个链接

    Most efficient method to detect column change in MS SQL Server

答案 1 :(得分:2)

SqlCacheDependency以及SqlDependency可以完全按照您的描述进行操作。两者都基于Query Notifications,这项技术允许您的应用程序在更新行时从服务器接收通知。您甚至可以从LINQ开始利用它。

但是你需要保持警惕,缓慢经常变化的价值观会造成更多的伤害而不是好处。您应该只使用相当稳定的值来执行此操作。