惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threatpost
Project Zero
Project Zero
Know Your Adversary
Know Your Adversary
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
T
Tenable Blog
Scott Helme
Scott Helme
T
Tor Project blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
NISL@THU
NISL@THU
Cisco Talos Blog
Cisco Talos Blog
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
S
Securelist
Help Net Security
Help Net Security
Google DeepMind News
Google DeepMind News
Cloudbric
Cloudbric
C
Check Point Blog
Jina AI
Jina AI
Webroot Blog
Webroot Blog
量子位
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
P
Privacy & Cybersecurity Law Blog
罗磊的独立博客
H
Heimdal Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
人人都是产品经理
人人都是产品经理
N
News and Events Feed by Topic
www.infosecurity-magazine.com
www.infosecurity-magazine.com
宝玉的分享
宝玉的分享
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
LINUX DO - 热门话题
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
PCI Perspectives
PCI Perspectives
Vercel News
Vercel News
N
News | PayPal Newsroom
A
Arctic Wolf
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
博客园 - 叶小钗
Y
Y Combinator Blog
V
V2EX
美团技术团队
O
OpenAI News
Microsoft Security Blog
Microsoft Security Blog
AWS News Blog
AWS News Blog

博客园 - 马伟

通过xrdp实现远程桌面连接Windows Azure linux虚拟机 使用VNC远程连接Windows Azure Linux虚拟机 设置Windows Azure Linux虚拟机中的root账户 使用Windows Azure PowerShell远程管理Windows Azure虚拟机 将SQL Azure数据库备份到本地SQL Server 2012 asp.net MVC3 “System.Web.Mvc.ModelClientValidationRule”问题 Session的生命周期 在ASP.NET中以编程方式设置母版页 ASP.NET自定义输出缓存提供程序 ASP.NET缓存依赖--自定义缓存依赖 QueryExtender控件之CustomExpression QueryExtender控件之OrderByExpression QueryExtender控件之PropertyExpression QueryExtender控件之RangeExpression QueryExtender控件之SearchExpession <<易学C#>>全书目录 用C#编程合并多个WORD文档 fckeditor编辑器上传文件出现invalid Request问题解决 荣获2009年“微软最有影响力开发者”
ASP.NET缓存依赖--SQL Server 2005与SQL Server 2008缓存依赖
马伟 · 2012-04-08 · via 博客园 - 马伟

      其实,在某些方案中,使用带有 SQL 依赖项的缓存可显著提高你的应用程序的性能。例如,假定你正在构建一个从数据库显示产品信息的电子商务应用程序。如果不进行缓存,则每当用户要查看产品时,应用程序都必须从数据库请求数据,执行相关的数据库连接、查询等命令。如果查询访问量很大时,这对于服务器与数据库来讲其耗费的资源是不可估量的。要解决这样的问题,你可以根据需要在某一时刻将产品信息缓存一天或者一段时间,由于产品信息已经在内存中,因此可确保较快的响应时间,从而也减少了数据库的访问量。
      但是,当数据库的产品信息发生变化时,缓存的产品信息就会失去与数据库中的产品信息的同步,且不同步的时间最长可达你设置的缓存时间(如一天)。其实,面对这样的不同步问题,使用 SQL 缓存依赖项可以缓存产品信息,并创建一个数据库表或行更改的依赖项。当且仅当数据更改时,基于该数据的缓存项便会失效并会从缓存中移除。下次从缓存中请求该项时,如果该项不在缓存中,便可以再次向缓存中添加更新后的版本,并且可确保具有最新的数据。
      在ASP.NET中,为你提供了SqlCacheDependency 类用于创建依赖于数据库中表或行的缓存项。当表中或特定行中发生更改时,带有依赖项的项便会失效,并会从缓存中移除。你可以在 Microsoft SQL Server 7.0、SQL Server 2000 、SQL Server 2005与SQL Server 2008中设置表的依赖项。因为Microsoft SQL Server 7.0与SQL Server 2000现在业界用的越来越少,就其实用性,下面我们就SQL Server 2005与SQL Server 2008缓存依赖做一个详细地阐述。
其实,SQL Server 2005与SQL Server 2008与理想的通知解决方案最为接近,它们实现了一种更改通知模型,可以向订阅了通知的应用程序服务器发送通知,而不是依赖早期版本的 SQL Server 中必需的轮询模型。如图所示,它们将通知基础结构以消息系统的模式内建在数据库内,叫做服务代理。服务代理管理队列,它们是具有相同标准的表、存储过程或者视图等数据库对象。

图:在SQL Server 2005与SQL Server 2008中监视数据的变化

                                 
       SQL Server 2005与SQL Server 2008监控对特定 SQL 命令的结果集的更改。如果数据库中发生了将修改该命令的结果集的更改,依赖项便会使缓存的项失效。此功能使得SQL Server 2005与SQL Server 2008可以提供行级别的通知。
      要使用SQL Server 2005与SQL Server 2008缓存依赖,你首先要做的就是启用通知,即确保数据库具有enable_broker标记设置。你可以用下面的SQL语句来执行这个动作:

use ASPNET4
alter database ASPNET4 set enable_broker

      通知支持 Select 查询和存储过程,支持多个查询和嵌套查询,但必须遵循如下规则:
      1)必须提供完全限定的表名,其中包括所有者名称,例如dbo.employee,如果你只写成employee就是不正确的。
      2)查询不支持聚合操作,例如count()、max()、min()或者average()。
      3)查询不能够使用通配符号(*)选择所有列。
      如下面就是一个可接受的命令:

select employeename from dbo.employee

      下面将通过一个详细的示例来阐述如何使用SQL Server 2005与SQL Server 2008缓存依赖。首先,我们需要在SqlServerDependency.aspx页面里定义了三个控件。其中,bt_Update控件用于修改数据库数据,bt_GetData控件用于获取缓存数据情况,lblInfo控件用于显示相关的操作信息。页面代码如代码清单19-1所示:
代码清单19-1:SqlServerDependency.aspx

<%@ Page Language="C#" AutoEventWireup="true"

CodeBehind="SqlServerDependency.aspx.cs"

Inherits="_19_1.SqlServerDependency" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:Button ID="bt_Update" runat="server"

Height="24px" Text="修改表" Width="100px"

         OnClick="bt_Update_Click" />

        <asp:Button ID="bt_GetData" runat="server"

Height="24px" Text="获取数据" Width="100px"

         OnClick="bt_GetData_Click" />

        <br />

        <br />

        <asp:Label ID="lblInfo" runat="server"

BorderStyle="Dotted" BorderWidth="1px"

Font-Size="12px" Width="500px">

</asp:Label>

    </div>

    </form>

</body>

</html>

     下面,我们需要在代码里完成这样几个功能:
     首先,在页面的Page_Load事件了创建一个SqlCacheDependency缓存依赖项;然后,在bt_GetData_Click事件里获取缓存数据的存在与否;最后,在bt_Update_Click事件里修改dbo.employee 表的employeename字段的值,从而使缓存项自动移除。如代码清单19-2所示:
     代码清单19-2:SqlServerDependency.aspx.cs

using System;

using System.Data;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Data.SqlClient;

using System.Web.Caching;

using System.Web.Configuration;

namespace _19_1

{

    public partial class SqlServerDependency : System.Web.UI.Page

    {

        private SqlCacheDependency dependency;

        private string connectionString = 

WebConfigurationManager.ConnectionStrings

["ConnectionString"].ConnectionString;

        protected void Page_Load(object sender, EventArgs e)

        {

            if (!this.IsPostBack)

            {

                SqlDependency.Stop(connectionString);

                SqlDependency.Start(connectionString);

                lblInfo.Text += "开始创建依赖项...<br />";

                Cache.Remove("employee");

                DataTable dt = GetTable();

                Cache.Insert("employee", dt, dependency);

                lblInfo.Text += "添加依赖项:

Cache.Insert(\"employee\", dt, dependency)<br />";

            }

        }

        private DataTable GetTable()

        {

            SqlConnection con = 

new SqlConnection(connectionString);

            using (con)

            {

                string sql = "select employeename from dbo.employee";

                SqlDataAdapter da = new SqlDataAdapter(sql, con);

                dependency = 

new SqlCacheDependency(da.SelectCommand);

                DataSet ds = new DataSet();

                da.Fill(ds, "employee");

                return ds.Tables[0];

            }

        }

        protected void bt_Update_Click(object sender, EventArgs e)

        {

            SqlConnection con = 

new SqlConnection(connectionString);

            using (con)

            {

                string sql = "update dbo.employee set 

employeename='mawei10' where employeeid=10";

                SqlCommand cmd = new SqlCommand(sql, con);

                con.Open();

                cmd.ExecuteNonQuery();

            }

            lblInfo.Text += 

"执行bt_Update_Click事件,修改完成.<br />";

        }

        protected void bt_GetData_Click(object sender, EventArgs e)

        {

            if (Cache["employee"] == null)

            {

                lblInfo.Text += "执行bt_GetData_Click事件,

Cache[\"employee\"]数据不存在.<br />";

            }

            else

            {

                lblInfo.Text += "执行bt_GetData_Click事件,

Cache[\"employee\"]数据还存在.<br />";

            }

        }

    }

}

      在上面的代码中,SqlDependency 对象表示应用程序和 SQL Server 2005 实例间的查询通知依赖关系。其中:
      SqlDependency.Start 方法启动用于接收依赖项更改通知的侦听器,该通知来自由连接字符串指定的 SQL Server 实例。如果侦听器初始化成功,则为 true;如果已存在兼容的侦听器,则为 false。
      SqlDependency.Stop 方法用于停止在上一次 Start 调用中指定的连接的侦听器。如果侦听器完全停止,则为 true;如果 AppDomain 从侦听器解除绑定,但至少还有一个其他 AppDomain 使用同一侦听器,则为 false。
     示例运行结果如图所示: