系列目录:
SqlCacheDependency使用轮流检测技术(轮询)使缓存无效
----------------------------------------------------------------------------------------------
通知是一项耗资源的任务,应选择变更频率较小的数据。
对于使用少数客户(Web服务器或组件服务器)同时为成百上千名用户提供服务的Web应用程序或中间层组件,最好使用SqlDependency类。因此,可以缓存大型表,但是在应用程序收到一个修改通知时,通过终止缓存以错开重新加载这些表的时机,只有在用户再次引用数据时,才会重新加载缓存。
SqlDependency是.net2.0封装的一个类型,在sql2005及以上版本才能使用。
使用方法:
1、必须在 MSDB 数据库中的 QueryNotificationService 服务上向Guest用户授予发送权限。方法如下,注意要区分大小写。 (我在做实时证并没有操作此步也可以运行,可能是以前就有此功能了吧)
GRANT SEND ON SERVICE::
[http://schemas.microsoft.com/SQL/Notifications/QueryNotificationService]
TO GUEST
2、启用CLR
在一个消息到达服务队列时,一个包含.Net代码的存储过程sp_DispatcherProc将使用一个队列来派发消息。因此必须启用Sql Server中的CLR功能。启用方法如下:
Exec sp_configure 'clr enabled',1
Reconfigure
--返回1表示true,返加0表示false
启动Service Broker语句如下:
Alter Database Northwind set enable_broker
4、使用SqlDependency。
建立一个WinFrom项目,窗口名称为FormDependency,在窗口上放一个DataGridView。编写下边代码。
using System.Configuration;
namespace SqlDependencyUse
{
public partial class FormDependency : Form
{
private static string connectString = ConfigurationManager.ConnectionStrings["NHibernateSampleDb"].ToString();
private delegate void GridDelegate(DataTable table);
private SqlDependency dep;
public FormDependency()
{
InitializeComponent();
}
private void FormDependency_Load(object sender, EventArgs e)
{
//启动一个与Sql Server进行通信的客户端进程
SqlDependency.Start(connectString);
UpdateGrid();
}
private void FormDependency_FormClosed(object sender, FormClosedEventArgs e)
{
//终止与Sql Server通信
SqlDependency.Stop(connectString);
}
private void UpdateGrid()
{
string sql = "select [CustomerId],[Firstname],[Lastname],[Version] from [dbo].[Customer]";
DataTable dt = new DataTable();
using (SqlConnection cn = new SqlConnection(connectString))
{
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cn.Open();
//SqlCommand对象包含一个Notification属性,可以将SqlCommand对象传递给SqlDependency对象的构造函数,以设置该属性。
dep = new SqlDependency(cmd);
//当有DML操作时,onChange事件会接收来自Sql Server通过sq_DispatcherProc存储过程发送给应用程序的消息。
dep.OnChange += new OnChangeEventHandler(dep_OnChange);
using (SqlDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
}
}
}
dgvView.Invoke(new GridDelegate(dgvDelegateMethod), dt);
}
private void dgvDelegateMethod(DataTable dtVal)
{
dgvView.DataSource = dtVal;
}
/// <summary>
/// SqlDependency的onChange事件处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void dep_OnChange(object sender, SqlNotificationEventArgs e)
{
System.Diagnostics.Debug.WriteLine("接收到事件");
if (e.Info == SqlNotificationInfo.Invalid)
{
MessageBox.Show("Invalid Statement");
return;
}
UpdateGrid();
}
}
}
注: 上边代码中的查询语句写法要非常严格。必须按SQL Server Service Broker提供制定规则的查询语句,一般来讲,必须是简单的sql查询语句(不能用*,不能用top,不能用函数,包括聚合函数,不能用子查询,包括where后的子查询,不能用外连接,自连接,不能用临时表,不能用变量,不能用视图,不能垮库,表名之前必须加类似dbo数据库所有者这样的前缀)例如:select * from table1,select column1 from table1,select count(*) from table1 都是错误的sql查询语句,select column1 from dbo.table1 则是正确的语句。
我刚刚测试时,发现始终无法触发onChange事件,让我郁闷了好长时间,后来发现SQL中没有加[dbo]。
5、测试,打开SqlServer,修改其中的数据。界面上DataGridView的数据也会一起更新。