校园新闻

您的位置: 首页> 教育教学> 学术交流>

用Sql2005与.net实现查询通知

时间: 2023-04-25 19:52:41 浏览次数:174


摘要 在本文中,将深入探讨如何把.NET2.0和Sql Server 2005的sever broker(查询通知)特征联合起来,以便通知应用程序何时关键数据发生变化进而达到消除反复查询数据库的目的。 关键字 SQL通知缓冲技术 Server Broker SqlDependency类

一、引言主动式通知(也称为“查询通知”),是微软ADO.NET和SQL Server小组协作开发的新成果。它允许你对数据进行缓冲并且仅在SQL Server中的数据发生变化时才发出通知;一旦接到通知,你就可以刷新相应的缓冲区或者采取其它必要的措施。 设想有一个典型的显示产品及其分类的电子商务网站。一个供应商的产品列表很可能并不经常发生变化,而其分类列表甚至更不会频繁更改。然而,在用户每次浏览该网站时,必须从数据库中反复查询这些列表。这显然是一种典型的低效资源利用,开发者和架构师都在绞尽脑汁想办法以减少这种浪费。缓冲技术正是“最小化”对这种几乎“停滞”的数据进行重复查询的技术之一。这种数据可以被进行一次性查询并存储在一个缓冲区中,而且应用程序可以从缓存中重复地存取数据。偶尔情况下,才更新缓存以得到新数据。但是,围绕更新缓存的时间调度方面出现了几个问题。该多长时间操作一次呢?例如,你每隔多长时间希望你的产品分类改变一次?每隔几个月一次?每隔两个月刷新一次该缓冲区如何?你知道会发生什么吗?就在你刷新缓存之后,分类被更新,而且在下一次刷新前在两个月的时间里它将保持陈旧。二、 .NET与Service Broker的通讯在SQL Server 2005中引入的一种新特征“Service Broker”使得查询通知成为可能。Service Broker把队列机制引入到数据库管理中,它使用一组队列与服务进行通讯,而服务反过来也知道如何往回通讯以调用相应的实体。其实,这些队列和服务都是一些与表、视图和存储过程一样的类对象。尽管完全可以在SQL Server内使用Service Broker,但是ADO.NET也知道如何与Service Broker进行通讯以触发这种机制并且从Service Broker中检索回通知。 在.NET一端,存在很多种“钩入”这种功能的方式。ADO.NET 2.0提供了System.Data.SqlClient.SqlDependency和System.Data.Sql.SqlNotificationRequest类。SqlDependency是SqlNotificationRequest的一种高级实现。当你看到通知的确从数据库中传来时,你可以分析一下相应变量的值,它是一个SqlNotificationEventArgs对象。SqlDependency总是随着OnChange事件返回这个对象,而且它是很有用的。其中,SqlNotificationInfo是一个具有18种可能值的枚举类型。三、为使用查询通知作准备因为默认情况下SQL Server 2005处于高度安全的状态,所以你需要“打开”一些功能才能使用查询通知。首先,你要使用的每一个数据库都需要启动Service Broker功能。为此,你可以在T-SQL中使用如下命令实现:USE 库名ALTER DATABASE 库名SET ENABLE_BROKER另外,你需要授予一些SQL Server权限以允许非管理员帐户能够参与使用查询通知。sqlClientPermission permission=new sqlClientPermission(permissionstate.unrestricted);Permission.Demand();四. SqlDependency.Start和StopSqlDependency和SqlCacheDependency都要求,在任何通知请求前先调用静态方法SqlDependency.Start()。这个方法负责创建一个SqlConnection以实现在数据改变时接收通知。注意,你仅需要在一个应用程序的生命周期的开始建立这些内容。

五、一个SQL通知实例下面,让我们开始使用SqlDependency来分析一下所有上面这些是如何协同工作的。using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Data.SqlClient;

namespace sql通知{public partial class Form1 : Form{private string connectionString = "Data Source=.;user id=sa;password=1234;Initial Catalog=HR;Pooling=False;";private delegate void GridDelegate(DataTable table);//定义委托对象:GridDelegateprivate SqlDependency dep; //sql通知对象public Form1(){ InitializeComponent();}private void Form1_Load(object sender, EventArgs e){SqlDependency.Start(connectionString); //在窗体启动的加载,启用SQL通知UpdateGrid();//调用UpdateGrid()方法.}private void Form1_FormClosed(object sender, FormClosedEventArgs e){SqlDependency.Stop(connectionString);//窗体关闭时候,停止SQL通知}private void UpdateGrid()//更新表格方法{string sql = "SELECT cemployeecode,vfirstname,vaddress,ccity FROM employee";DataTable dt = new DataTable();using (SqlConnection cn = new SqlConnection(connectionString)) {using (SqlCommand cmd = new SqlCommand(sql, cn)){cn.Open();//通知对象和SQLCommand对象关联,当有通知产生的时候,则执行sqlCommand 对象语句dep = new SqlDependency(cmd); dep.OnChange += dep_OnChange;//通知改变事件.//通过执行sql语句,返回employee表中的所有数据,给rdr对象using (SqlDataReader rdr = cmd.ExecuteReader()){ dt.Load(rdr); //将rdr加载到dt(数据表对象)}}}dataGridView1.Invoke((GridDelegate)delegate(DataTable table)//Invoke:调用委托对象{dataGridView1.DataSource = table;}, dt);}//什么时候响应dep_OnChange事件.private void dep_OnChange(Object sender, SqlNotificationEventArgs e){MessageBox.Show("数据已经更新了");//提示用户数据改变if (e.Info == SqlNotificationInfo.Invalid)//如果不能与数据库响应显示一个错误提示{MessageBox.Show("Invalid");return;}UpdateGrid();//如果有改变,则更新表格.}}}

六、注意事项关于SqlDependency类,很多人无法测试成功,因为它的限制很多,功能可能有待加强,稍微不注意就会让上面的代码陷入死循环。特别要注意的就是command的sql语句问题:select id,name from dbo.test where id<>4 order by id desc 很遗憾,他只能支持上面这样的简单语句列名必须写,不能用*,不能用top,不能用函数,包括聚合函数,不能用子查询,包括where后的子查询,不能用外连接,自连接,不能用临时表,不能用变量,不能用视图等等如:select * from table1,select column1 from table1,select count(*) from table1 都是错误的sql查询语句七、结论尽管查询通知是.NET 2.0中最重要的特征之一,但是目前它仍然难与其它优秀特征(例如ASP.NET中的泛型或UI魔术等)相衔接。然而,无论你使用它来防止针对于含有数百个项的下拉列表框的连续的反复查询,还是使用它来管理基于Web的上百万的客户端计算机的更新,它都能有效地帮助你减少资源开支。查询通知可以成为创建可扩展的具有响应性的应用程序的强有力的协作开发工具。