利用ADO.NET 2.0和SQL Server 2005实现数据流

在现代应用程序中,实现数据流的方式多种多样,有些方法效果不错,而有些则更为优秀。本文将探讨使用ADO.NET2.0的SqlDependency和SQL Server 2005来实现应用程序实例之间的数据流。这个简单的聊天程序将展示其用法,并测试这些新特性的潜力。

注意事项

本示例使用了SQL Server 2005和ADO.NET2.0的特性,并使用Visual Studio 2005创建。

SQL Server 2005

SQL Server2005引入了许多新特性,其中包括服务代理(Service Broker)和查询通知(Query Notifications)。服务代理是一个内置于SQL Server 2005的队列式、可靠的消息传递机制,提供了一个健壮的异步编程模型。本文不涵盖服务代理的详细信息,更多信息可以在MSDN找到。

查询通知允许应用程序在查询结果发生变化时收到通知,这通过不必定期查询数据库来改进性能。更多信息可以在MSDN找到。

数据库

本示例的数据库并不复杂,仅足以演示本文的特性。有两个表:Message和Person。Person存储应用程序的用户,而Message存储发送的消息。要使用SqlDependency,数据库必须支持服务代理。如果数据库未启用此选项,则需要启用它。

ALTER DATABASE Chatter SET ENABLE_BROKER

SqlNotificationRequest也可以提供相同的服务,但它需要大量的手动设置。SqlDependency为设置了管道。虽然它更简单易实现,但它显然不允许某些应用程序可能需要的自定义程度,对于这些应用程序,SqlNotificationRequest将是最佳选择。

依赖关系

通过SqlCommand在应用程序和数据库之间创建依赖关系。在建立此依赖关系之前,必须为此会话启动SqlDependency。

SqlDependency.Start(m_ConnectionString);

处理此命令后,SQL Server将自动在连接字符串中指定的数据库中创建一个队列和一个服务。为了创建这个队列,数据库用户必须具有SUBSCRIBE QUERY NOTIFICATIONS权限。如所见,GUID用于命名这些对象。每次运行应用程序时,都会生成一个新的GUID,并创建一个新的队列和服务。尽管文档表示这些将在应用程序退出时被移除,但发现情况并非如此。

如前所述,依赖关系是基于SqlCommand创建的。

SqlDependency dependency = new SqlDependency(cmd);

当然,对于可以包含在此命令中的内容有一些限制。命令必须使用两部分名称,并且不能使用*。它显然也不能是UPDATE或INSERT语句。

以下内容将不起作用:

SELECT * FROM Message

以下内容将起作用:

SELECT ID, Message FROM dbo.Message

如果查询不正确,将立即发送事件:

SqlNotificationEventArgs.Info = Query SqlNotificationEventArgs.Source = Statement SqlNotificationEventArgs.Type = Subscribe

非常模糊的解释是“该语句对于通知无效”。不幸的是,还没有找到一个好的资源来说明什么构成了有效的语句。在测试过程中,使用了被证明有效的内联SQL语句,然后使用了具有完全相同语句的存储过程,它被证明是无效的。

一旦设置好依赖关系并且应用程序正在运行,所要做的就是坐下来等待接收事件。

在这个示例应用程序中,当用户发送新消息时,它将被插入到数据库中,这将导致消息被发送到服务代理队列,并被通知服务接收,进而触发OnChange事件,由应用程序处理。

void OnChange(object sender, SqlNotificationEventArgs e) { SqlDependency dependency = sender as SqlDependency; // Notices are only a one shot deal dependency.OnChange -= OnChange; // Fire the event if (OnNewMessage != null) { OnNewMessage(); } }

通知是一次性的,因此在接收到事件后,必须重新连接以继续接收通知。在示例应用程序中,OnChange事件被移除,并向客户端触发事件,这将重新加载消息并导致依赖关系重新建立。

public DataTable GetMessages() { DataTable dt = new DataTable(); try { // Create command // Command must use two part names for tables // SELECT FROM dbo.Table rather than // SELECT FROM Table // Query also can not use *, fields // must be designated SqlCommand cmd = new SqlCommand("usp_GetMessages", m_sqlConn); cmd.CommandType = CommandType.StoredProcedure; // Clear any existing notifications cmd.Notification = null; // Create the dependency for this command SqlDependency dependency = new SqlDependency(cmd); // Add the event handler dependency.OnChange += new OnChangeEventHandler(OnChange); // Open the connection if necessary if (m_sqlConn.State == ConnectionState.Closed) m_sqlConn.Open(); // Get the messages dt.Load(cmd.ExecuteReader(CommandBehavior.CloseConnection)); } catch (Exception ex) { throw ex; } return dt; }

会注意到,不需要保持数据库连接即可接收更改事件。

本文和示例只是对SQL Server2005和ADO.NET2.0的新特性之一的快速介绍,以及它如何在应用程序中使用。

这些特性当然非常新,信息仍然有些模糊。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485