阿宽

Nothing is more powerful than habit!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SqlDependency缓存用法

Posted on 2011-02-25 15:16  宽田  阅读(3171)  评论(0编辑  收藏  举报

系列目录:

SqlDependency缓存用法

Asp.net使用SqlDependency

SqlCacheDependency使用命令通知使缓存无效

CacheDependency用法

AggregateCacheDependency 用法

SqlCacheDependency使用轮流检测技术(轮询)使缓存无效

----------------------------------------------------------------------------------------------

 

 

    在Microsoft SQL Server数据库中的数据发生变化时,SqlDependency类能够提供一种方法,将这种变化通知应用程序。可以使用这种通知来终止缓存和重新加载数据库服务器中的数据。
    通知是一项耗资源的任务,应选择变更频率较小的数据。
    对于使用少数客户(Web服务器或组件服务器)同时为成百上千名用户提供服务的Web应用程序或中间层组件,最好使用SqlDependency类。因此,可以缓存大型表,但是在应用程序收到一个修改通知时,通过终止缓存以错开重新加载这些表的时机,只有在用户再次引用数据时,才会重新加载缓存。

    SqlDependency是.net2.0封装的一个类型,在sql2005及以上版本才能使用。

使用方法:

1、必须在 MSDB 数据库中的 QueryNotificationService 服务上向Guest用户授予发送权限。方法如下,注意要区分大小写。 (我在做实时证并没有操作此步也可以运行,可能是以前就有此功能了吧)

USE MSDB
GRANT SEND ON SERVICE::
[http://schemas.microsoft.com/SQL/Notifications/QueryNotificationService]
TO GUEST

 

2、启用CLR
在一个消息到达服务队列时,一个包含.Net代码的存储过程sp_DispatcherProc将使用一个队列来派发消息。因此必须启用Sql Server中的CLR功能。启用方法如下:

Use Master
Exec sp_configure 'clr enabled',1
Reconfigure

 

3、SqlDependency 对象会使用 Service Broker 将消息发送给 QueryNotificationService服务,所以需要启用 Service Broker。可以通过下边语句查看是否启用。
select DatabasePropertyex('Northwind','IsBrokerEnabled')
--返回1表示true,返加0表示false

 

    启动Service Broker语句如下:

use master
Alter Database Northwind set enable_broker

 

 

4、使用SqlDependency。

建立一个WinFrom项目,窗口名称为FormDependency,在窗口上放一个DataGridView。编写下边代码。

using System.Data.SqlClient;
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的数据也会一起更新。