设置具体数据库启动Service Broker服务,如下图:
我这里试例数据库的名字为“ghj_Demo”,修改 Broker Enabled 属性为 true。
你也可以用SQL 语句来修改,修改的SQL语句如下:
ALTER DATABASE ghj_Demo SET ENABLE_BROKER
确保你将使用的数据库帐户具有必需的权限
你在后面连接这个数据库的帐户,要确保对这个数据库具有 SUBSCRIBE、 QUERY 、NOTIFICATIONS 的权限。
下面就是一个简单的代码例子,来演示查询通知。这里用到一个我自己建立的表:
这个表结构如下:
CREATE TABLE [dbo].[User]( [UserName] [nvarchar](20) NOT NULL, [Email] [nvarchar](50) NULL ) ON [PRIMARY] GO
演示的控制台代码如下:
using System; using System.Data; using System.Data.SqlClient; namespace Demo { class Program { public static string connectionstring = "Data Source=.;Initial Catalog=ghj_Demo;Integrated Security=True"; public void DoDependency() { using (SqlConnection conn = new SqlConnection(connectionstring)) { // sql is a local procedure that returns // a paramaterized SQL string. You might want // to use a stored procedure in your application. string sql = "select [UserName] ,[Email] from dbo.[User]"; SqlCommand cmd = new SqlCommand(sql, conn); // Ensure the command object does not have a notification object. cmd.Notification = null; //Notification specific code SqlDependency dep = new SqlDependency(cmd); dep.OnChange += new OnChangeEventHandler(TestEvent); conn.Open(); SqlDataReader r = cmd.ExecuteReader(); //Read the data here and close the reader r.Close(); conn.Close(); Console.WriteLine("DataReader Read..."); } } void TestEvent(Object o, SqlNotificationEventArgs args) { // 注意: // 如果Server端在很短的时间内发生了大量的改动(比如用了一个循环Update了好多行), // OnChanged必须能迅速处理事件,否则它只会被触发一次。这个不是缺陷, // 因为一般OnChanged事件处理函数内都要执行类似刷新缓存的操作,它只触发一次, // 不会影响程序逻辑,却能提高程序性能。 Console.WriteLine("======================"); Console.WriteLine("Event Recd"); Console.WriteLine("Info:" + args.Info); Console.WriteLine("Source:" + args.Source); Console.WriteLine("Type:" + args.Type); } static void Main(string[] args) { // In order to use the callback feature of the // SqlDependency, the application must have // the SqlClientPermission permission. try { SqlClientPermission perm = new SqlClientPermission(
System.Security.Permissions.PermissionState.Unrestricted); perm.Demand(); } catch { throw new ApplicationException("No permission"); } try { SqlDependency.Stop(connectionstring); //Start the listener infrastructure on the client SqlDependency.Start(connectionstring); Program q = new Program(); q.DoDependency(); Console.WriteLine("Wait for Notification Event..."); Console.Read(); } finally { //Optional step to clean up dependency else it will fallback to automatic cleanup SqlDependency.Stop(connectionstring); } } } }
一些注意事项:摘自MSDN文档
使用查询通知功能的应用程序需要考虑下列特殊注意事项。
注意事项 | 说明 |
SQL Server 的服务帐户 | 对于使用本地系统帐户作为服务帐户的 SQL Server 实例,应用程序不会从其接收通知。 |
接收通知 | 无法在运行 Windows 95 或 Windows 98 的计算机上接收通知。 |
查询通知和事务 | 如果在某一事务内进行了多项影响具有已注册通知请求的一组数据的修改,则仅会发送单个通知事件。 |
快速更新和查询通知 | 使用查询通知的应用程序必须考虑到立即出现通知的情况。服务器上的数据更改时,通知消息将发送到相应的服务中介程序队列。 应用程序需要注册才能接收其他通知。 因此,如果多个应用程序快速更新某个数据集,应用程序在缓存刷新后,立即可以接收通知,检索数据,然后获取另一个更新通知。 编写使用查询通知的应用程序时必须考虑到此情况。 如果应用程序使用不断更新的数据,则可能更适合使用另一种数据缓存策略。 |
设置选项设置 | 在通知请求下执行 SELECT 语句时,提交请求的连接必须设置以下选项: · ANSI_NULLS ON · ANSI_PADDING ON · ANSI_WARNINGS ON · CONCAT_NULL_YIELDS_NULL ON · QUOTED_IDENTIFIER ON · NUMERIC_ROUNDABORT OFF · ARITHABORT ON |
编写通知查询语句的约束
您可以为 SELECT 和 EXECUTE 语句设置通知。 使用 EXECUTE 语句时,SQL Server 会为执行的命令而不是 EXECUTE 语句本身注册通知。 该命令必须满足 SELECT 语句的要求和限制。 当注册通知的命令包含多个语句时,数据库引擎会为批处理中的每个语句创建一个通知。
对满足以下要求的 SELECT 语句支持查询通知:
-
SELECT 语句中的提取的列必须显式声明,且表名称必须用由两部分组成的名称进行限定。 请注意,这意味着语句中引用的所有表都必须位于同一个数据库中。
-
语句不能使用星号 (*) 或 table_name.* 语法来指定列。
-
语句不能使用未命名的列或重复的列名称。
-
语句必须引用一个基表。
-
SELECT 语句中的提取的列不能包含聚合表达式,除非该语句使用 GROUP BY 表达式。 在提供 GROUP BY 表达式的情况下,选择列表可以包含聚合函数 COUNT_BIG() 或 SUM()。 不过,不能为可以为 null 的列指定 SUM()。 语句不能指定 HAVING、CUBE 或 ROLLUP。
-
SELECT 语句中的提取的列用作简单表达式时不能出现多次。
-
语句不能包含 PIVOT 或 UNPIVOT 运算符。
-
语句不能包含 INTERSECT 或 EXCEPT 运算符。
-
语句不能引用视图。
-
语句不能包含以下任一项: DISTINCT、COMPUTE、COMPUTE BY 或 INTO。
-
语句不能引用服务器全局变量 (@@variable_name)。
-
语句不能引用派生表、临时表或表变量。
-
语句不能引用其他数据库或服务器中的表或视图。
-
语句不能包含子查询、外部联接或自联接。
-
语句不能引用大型对象类型: text、ntext 和 image。
-
语句不能使用 CONTAINS 或 FREETEXT 全文谓词。
-
语句不能使用行集合函数,包括 OPENQUERY 和 OPENROWSET。
-
语句不能使用以下任一集合函数: AVG、COUNT(*)、MAX、MIN、STDEV、STDEVP、VAR 或 VARP。
-
语句不能使用任何不确定性函数,包括排名和开窗函数。
-
语句不能包含用户定义的聚合。
-
语句不能引用系统表或视图,包括目录视图和动态管理视图。
-
语句不能包含 FOR BROWSE 信息。
-
语句不能引用队列。
-
语句不能包含无法更改或无法返回结果的条件语句(例如 WHERE 1=0)。
sunmast 对查询通知的注意事情也有很多有价值的整理:
使用SQL Server 2005 Query Notification的几个注意事项
http://blog.joycode.com/sunmast/archive/2006/08/11/sql_2005_query_notification_comments_79814.aspx
参考资料:
剖析SQL Server 2005查询通知之基础
http://www.allwiki.com/wiki/%E5%89%96%E6%9E%90SQL_Server_2005%E6%9F%A5%E8%AF%A2%E9%80%9A%E7%9F%A5%E4%B9%8B%E5%9F%BA%E7%A1%80
Using SqlDependency for data change events
http://www.codeproject.com/KB/database/chatter.aspx
SQL Server 2005 Service Broker 初探
http://msdn.microsoft.com/zh-cn/library/ms345108.aspx
SQL Server 2005数据库开发详解
http://book.csdn.net/bookfiles/24/10024713.shtml
C# Windows 应用程序中实现 SQL Server 2005 查询通知
http://support.microsoft.com/kb/555893/zh-cn
SqlDependency changes for RTM [Sushil Chordia]
http://blogs.msdn.com/dataaccess/archive/2005/09/27/474447.aspx
.NET 2.0 SqlDependency快速上手指南
http://www.cnblogs.com/Xrinehart/archive/2006/07/27/461106.html
在 Windows 应用程序中使用 SqlDependency
http://msdn.microsoft.com/zh-cn/library/a52dhwx7(VS.80).aspx
Using SqlDependency in an ASP.NET Application
http://msdn.microsoft.com/en-us/library/9dz445ks(VS.80).aspx
Minimum Database Permissions Required for SqlDependency
http://www.codeproject.com/KB/database/SqlDependencyPermissions.aspx
使用SQL Server 2005 Query Notification的几个注意事项
http://blog.joycode.com/sunmast/archive/2006/08/11/sql_2005_query_notification_comments_79814.aspx