一切皆有可能

SLEEPY BUT POWERFUL (A.K.A 速马) Creative Commons License
随笔 - 43, 评论 - 483, 引用 - 14

导航

关于

我

联系方式 (夏桅 xia4 wei2)

译作

 

三章样章阅读
[CSDN读书频道提供]

 

想做点好事的来看看

一字不识的藏族同胞阿牛创办的完全免费学校

 

MVP Profile

Visual Developer - .NET/C#

Visitors

Locations of visitors to this page

标签

每月存档

最新留言

广告

使用SQL Server 2005 Query Notification的几个注意事项

Using Query Notifications:http://msdn2.microsoft.com/en-us/library/t9x04ed2.aspx

  1. Query Notification不同于Notification Service,最简单的理由是我压根就没装Notification Service也能用它。看BOL文档,Notification Service似乎不只是应用程序级别的服务。
  2. SqlDependency和SqlCacheDependency的实现是不同的。SqlCacheDependency是基于poll模式定时轮询实现的(默认情况),而SqlDependency的是push模型(这意味着SqlDependency性能更高且更可靠)。不过,SqlCacheDependency可以基于SqlDependency实现,但MSDN只是提到“The SqlCacheDependency class also supports integration with the System.Data.SqlClient.SqlDependency class when using a SQL Server 2005 database. ”,但没有给出例子。我Goo了半天才发现Quickstart里面有:
    http://x/QuickStartv20/aspnet/doc/caching/SQLInvalidation.aspx
  3. SQL Server 2005 EXPRESS也支持Query Notification,但默认似乎是关闭的,并且我也没能在配制工具找到配制界面。事实上不管怎么说只要能开启Broker服务就OK。这可以通过ALTER DATABASE [Your DB Name] SET ENABLE_BROKER命令实现。(后来找到了个相关的,在Management Studio的Object Explorer,Databases|Your DB Name|Properties|Permissions|Subscrib query notifications)
  4. SqlDependency.OnChange Event会报告订阅过程中出现的所有事件,比如订阅失败,而不只是Server端数据改变的情形。假如你在这个事件绑定函数中又重新注册了Query Notification,小心产生死循环。
  5. 使用Query Notification是有限制的,并且不是所有的查询都支持(否则产生订阅失败事件),具体规则是:
    http://msdn2.microsoft.com/en-us/library/aewzkxxh.aspx

    The projected columns in the SELECT statement must be explicitly stated, and table names must be qualified with two-part names. Notice that this means that all tables referenced in the statement must be in the same database.
    The statement may not use the asterisk (*) or table_name.* syntax to specify columns.
    The statement may not use unnamed columns or duplicate column names.
    The statement must reference a base table.
    The projected columns in the SELECT statement may not contain aggregate expressions unless the statement uses a GROUP BY expression. When a GROUP BY expression is provided, the select list may contain the aggregate functions COUNT_BIG() or SUM(). However, SUM() may not be specified for a nullable column. The statement may not specify HAVING, CUBE, or ROLLUP.
    A projected column in the SELECT statement that is used as a simple expression must not appear more than once.
    The statement must not include PIVOT or UNPIVOT operators.
    The statement must not include the INTERSECT or EXCEPT operators.
    The statement must not reference a view.
    The statement must not contain any of the following: DISTINCT, COMPUTE or COMPUTE BY, or INTO.
    The statement must not reference server global variables (@@variable_name).
    The statement must not reference derived tables, temporary tables, or table variables.
    The statement must not reference tables or views from other databases or servers.
    The statement must not contain subqueries, outer joins, or self-joins.
    The statement must not reference the large object types: text, ntext, and image.
    The statement must not use the CONTAINS or FREETEXT full-text predicates.
    The statement must not use rowset functions, including OPENROWSET and OPENQUERY.
    The statement must not use any of the following aggregate functions: AVG, COUNT(*), MAX, MIN, STDEV, STDEVP, VAR, or VARP.
    The statement must not use any nondeterministic functions, including ranking and windowing functions.
    The statement must not contain user-defined aggregates.
    The statement must not reference system tables or views, including catalog views and dynamic management views.
    The statement must not include FOR BROWSE information.
    The statement must not reference a queue.
    The statement must not contain conditional statements that cannot change and cannot return results (for example, WHERE 1=0).
  6. 订阅成功后,SQL Server会自动创建一个dbo.SqlQueryNotificationStoredProcedure-[GUID]这样存储过程。订阅结束后(应用程序退出或者SqlDependency.Stop方法被调用),这个存储过程会被自动删除。
  7. 关于行级别的缓存失效功能(子曰“Row level cache invalidation”),看上去目前还没有实现(至少我还没找到办法访问这个功能)。但世事无绝对,现在你可以用托管代码编写触发器,再建个临时表,间接的实现(也许你已经有主意了)
  8. 有时候Query Notification会在没有任何征兆的情况下突然不工作(真要命~),原因可能是你没有安装这个补丁:http://support.microsoft.com/kb/913364/EN-US/ 。实际情况是SQL Server已经发出了消息,客户端也已经接收到,但是OnChange事件没有触发。。。所以这是个.NET 2.0框架的补丁。
  9. 测试过程中,如果SQL Server在数据改变时报告了其它错误(红色的X!),需要特别注意,可能是配置错误(比如权限不足),Query Notification也会停止工作,但SQL Server会不断地重试(时间间隔大约是一分钟左右),导致EventLog里面出现了长长的错误列表(比较醒目~)。使用SELECT * FROM sys.transmission_queue命令查看队列中所有待发的消息通知,注意最后一列[transmission_status]的值。
  10. 数据库迁移到另一台机器后(Attach/Detach,Backup/Restore),可能会碰到这个错误:“An exception occurred while enqueueing a message in the target queue. Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.”,这样Query Notification也不会工作。这个原因是原先创建数据库的用户在新的机器上不再有效,可以使用这个命令搞定之:ALTER AUTHORIZATION ON DATABASE::[Your DB Name] TO [sa]
  11. 如果你的程序在调用了SqlDependency.Start后却忘了调用SqlDependency.Stop就退出了,那么程序再次启动时,在EventLog你可能会看到这样的提示:The query notification dialog on conversation handle '{GUID}.' closed due to the following error: Cannot find the remote service 'SqlQueryNotificationService-GUID' because it does not exist.
    这是因为SQL Server找不到原先注册的Subscriber所致,所以SQL Server会自动注销这个Subscriber,不会影响程序功能。但你却得注意SqlDependency.Stop没有被调用,程序逻辑可能有问题。而且SQL Server端的Broker队列会积压所有待发的消息(因为发不出去),可能会给Server端造成无谓的压力。
    在基于Visual Studio 2005的Web应用程序开发中,如果你使用Visual Studio内置的Web Server,那么当这个Server关闭时,不会等Application_End函数执行完毕就有可能退出(这个应该算是个小小的Bug)。假如你把SqlDependency.Stop放在了这个函数里面,那每次启动调试你大概都能收到SQL Server的这个提示信息。IIS不存在这个问题。
  12. 如果Server端在很短的时间内发生了大量的改动(比如用了一个循环Update了好多行),OnChanged必须能迅速处理事件,否则它只会被触发一次。这个不是缺陷,因为一般OnChanged事件处理函数内都要执行类似刷新缓存的操作,它只触发一次,不会影响程序逻辑,却能提高程序性能。
  13. SqlDependency构造函数有个options选项,MSDN的文档给链接到了错误的地方。我原来以为可以通过这个选项来过滤掉一些不必要的事件通知(比如我不想监视所有删除操作的事件),但事实上它是用来定义Service Broker实例名等参数的,就像一个SQL连接字符串。

// updating

posted on 2006-08-11 23:15:00 by sunmast  评论(4) 阅读(9872)

Powered by: Joycode.MVC引擎 0.5.2.0