ASP.NET 应用程序中的 SqlDependency

本节中的示例演示了如何通过利用 ASP.NET SqlCacheDependency 对象间接使用 SqlDependencySqlCacheDependency 对象使用 SqlDependency 侦听通知并正确更新缓存。

注意

该示例代码假定你已通过执行启用查询通知中的脚本启用了查询通知。

关于示例应用程序

示例应用程序使用单个 ASP.NET 网页在 GridView 控件中显示 AdventureWorks SQL Server 数据库中的产品信息。 页面加载完成后,代码会将当前时间写入 Label 控件。 然后,它定义一个 SqlCacheDependency 对象并设置 Cache 对象的属性,以存储最多三分钟的缓存数据。 然后代码将连接到数据库并检索数据。 当页面加载完成且应用程序运行时,ASP.NET 将从缓存中检索数据,如注意到页面上的时间未更改,则可以确认此情况。 如果受到监视的数据发生更改,ASP.NET 将使缓存失效,并在 GridView 控件中重新填充新数据,同时更新 Label 控件中显示的时间。

创建示例应用程序

执行以下步骤以创建和运行示例应用程序:

  1. 创建新的 ASP.NET 网站。

  2. 向 Default.aspx 页面添加 LabelGridView 控件。

  3. 打开页面的类模块并添加以下指令:

    Option Strict On  
    Option Explicit On  
    
    Imports System.Data.SqlClient  
    
    using System.Data.SqlClient;  
    using System.Web.Caching;  
    
  4. 在页面的 Page_Load 事件中添加以下代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = "Cache Refresh: " +
        DateTime.Now.ToLongTimeString();
    
        // Create a dependency connection to the database.
        SqlDependency.Start(GetConnectionString());
    
        using (SqlConnection connection =
            new SqlConnection(GetConnectionString()))
        {
            using (SqlCommand command =
                new SqlCommand(GetSQL(), connection))
            {
                SqlCacheDependency dependency =
                    new SqlCacheDependency(command);
                // Refresh the cache after the number of minutes
                // listed below if a change does not occur.
                // This value could be stored in a configuration file.
                int numberOfMinutes = 3;
                DateTime expires =
                    DateTime.Now.AddMinutes(numberOfMinutes);
    
                Response.Cache.SetExpires(expires);
                Response.Cache.SetCacheability(HttpCacheability.Public);
                Response.Cache.SetValidUntilExpires(true);
    
                Response.AddCacheDependency(dependency);
    
                connection.Open();
    
                GridView1.DataSource = command.ExecuteReader();
                GridView1.DataBind();
            }
        }
    }
    
    Protected Sub Page_Load(ByVal sender As Object, _
       ByVal e As System.EventArgs) Handles Me.Load
    
        Label1.Text = "Cache Refresh: " & _
           Date.Now.ToLongTimeString()
    
        ' Create a dependency connection to the database
        SqlDependency.Start(GetConnectionString())
    
        Using connection As New SqlConnection(GetConnectionString())
            Using command As New SqlCommand(GetSQL(), connection)
                Dim dependency As New SqlCacheDependency(command)
    
                ' Refresh the cache after the number of minutes
                ' listed below if a change does not occur.
                ' This value could be stored in a configuration file.
                Dim numberOfMinutes As Integer = 3
                Dim expires As Date = _
                    DateTime.Now.AddMinutes(numberOfMinutes)
    
                Response.Cache.SetExpires(expires)
                Response.Cache.SetCacheability(HttpCacheability.Public)
                Response.Cache.SetValidUntilExpires(True)
    
                Response.AddCacheDependency(dependency)
    
                connection.Open()
    
                GridView1.DataSource = command.ExecuteReader()
                GridView1.DataBind()
            End Using
        End Using
    End Sub
    
  5. 添加两个帮助程序方法:GetConnectionStringGetSQL。 已定义的连接字符串使用集成安全性。 你将需要验证所使用的帐户是否具有必要的数据库权限,并且示例数据库 AdventureWorks 是否启用了通知

    private string GetConnectionString()
    {
        // To avoid storing the connection string in your code,
        // you can retrieve it from a configuration file.
        return "Data Source=(local);Integrated Security=true;" +
          "Initial Catalog=AdventureWorks;";
    }
    private string GetSQL()
    {
        return "SELECT Production.Product.ProductID, " +
        "Production.Product.Name, " +
        "Production.Location.Name AS Location, " +
        "Production.ProductInventory.Quantity " +
        "FROM Production.Product INNER JOIN " +
        "Production.ProductInventory " +
        "ON Production.Product.ProductID = " +
        "Production.ProductInventory.ProductID " +
        "INNER JOIN Production.Location " +
        "ON Production.ProductInventory.LocationID = " +
        "Production.Location.LocationID " +
        "WHERE ( Production.ProductInventory.Quantity <= 100 ) " +
        "ORDER BY Production.ProductInventory.Quantity, " +
        "Production.Product.Name;";
    }
    
    Private Function GetConnectionString() As String
        ' To avoid storing the connection string in your code,
        ' you can retrieve it from a configuration file.
    
        Return "Data Source=(local);Integrated Security=true;" & _
         "Initial Catalog=AdventureWorks;"
    End Function
    
    Private Function GetSQL() As String
        Return "SELECT Production.Product.ProductID, " & _
        "Production.Product.Name, " & _
        "Production.Location.Name AS Location, " & _
        "Production.ProductInventory.Quantity " & _
        "FROM Production.Product INNER JOIN " & _
        "Production.ProductInventory " & _
        "ON Production.Product.ProductID = " & _
        "Production.ProductInventory.ProductID " & _
        "INNER JOIN Production.Location " & _
        "ON Production.ProductInventory.LocationID = " & _
        "Production.Location.LocationID " & _
        "WHERE ( Production.ProductInventory.Quantity <= 100) " & _
        "ORDER BY Production.ProductInventory.Quantity, " & _
        "Production.Product.Name;"
    End Function
    

测试应用程序

应用程序会缓存 Web 窗体上显示的数据,在没有任何活动的情况下,每三分钟刷新一次数据。 如果数据库发生了更改,则立即刷新缓存。 从 Visual Studio 中运行应用程序,这样会将页面加载到浏览器中。 显示的缓存刷新时间指示上次刷新缓存的时间。 等待三分钟,然后刷新页面,从而导致发生回发事件。 请注意,页面上显示的时间已更改。 如果在不到三分钟的时间内刷新页面,则页面上显示的时间将保持不变。

现在,使用 Transact-SQL UPDATE 命令更新数据库中的数据并刷新页面。 此时显示的时间表示已使用数据库中的新数据刷新缓存。 请注意,尽管缓存已更新,但在回发事件发生之前,页面上显示的时间不会更改。

使用 SQL 依赖项进行分布式缓存同步

有些第三方分布式缓存(如 NCache)支持使用 SQL 依赖项同步 SQL 数据库和缓存。 有关详细信息和示例源代码实现,请参阅分布式缓存 SQL 依赖项示例

请参阅