Office中国论坛/Access中国论坛
标题: 在SQL服务器中使用MSMQ组件实现网络内异步通讯 [打印本页]
作者: 阿罗 时间: 2003-9-21 00:52
标题: 在SQL服务器中使用MSMQ组件实现网络内异步通讯
几天前碰到这么一个问题,在公司里,如果有一个人出差,他想把他的部分权限委托给另外一个同事。一个比较容易想到的办法就是用一个隐藏的窗体定时向SQL服务器查询特定表,如果有新的委托记录,则在客户端处理。但是分析以后,认为这个方法虽然原理简单,但是在实施过程中有不少问题。主要的问题是,工作委托并不是频繁发生的事件,可能整天也就数起,为了这样一个功能,大大加重了服务器和网络的负担,非常的不经济。另外,如果某个人已经出差在外,而想变更委托时,实时处理变得要求太高。
后来想到用消息队列来解决这个问题。在查找资料时,找到这么一篇文章,很有针对性。后来我就按照他来进行一些试验,结论是完全可行。同时,也找到其他的一些文章,MSMQ应该有更广泛的应用价值。现在把我找到的资料和试验结果同大家分享,希望能起到抛砖引玉的效果。
这篇是关于如何在SQL服务器里使用一个MSMQ组件的例子:
http://www.tagconsulting.com/Show.asp?Id=1000
[此贴子已经被作者于2003-9-23 11:31:37编辑过]
作者: 阿罗 时间: 2003-9-21 00:55
为了以后万一这个连接失效,现在把整篇文章拷贝下来:
[B]Update MSMQ from SQL[/B]
Introduction
One of the problems that we recently faced was the need to post a message to MSMQ when the data in a SQL table was changed. An extensive search of the various resources that we have led us to this solution. And, although it seems to be complicated, it appears to be the only way, at the moment, to accomplish our goal
First, we created a Visual Basic ActiveX DLL project that will actually talk to the Message Queue. We chose to expose a single method called Send. The code appears below.
=============================================
Public Sub Send(QueuePath As String, Label As String, Body As String)
Dim msg As MSMQMessage
Dim QI As MSMQQueueInfo
Dim RequestQueue As MSMQQueue
Set QI = New MSMQQueueInfo
QI.PathName = QueuePath
Set RequestQueue = QI.Open(MQ_SEND_ACCESS, MQ_DENY_NONE)
Set msg = New MSMQMessage
msg.Label = Label
msg.Body = Body
msg.Send RequestQueue
Set msg = Nothing
RequestQueue.Close
Set msg = Nothing
Set RequestQueue = Nothing
Set QI = Nothing
End Sub
==================================================
As you can see, this is relatively straightforward code. Once we have compiled and deployed this component onto the SQL Server machine, we create a stored procedure that will instantiate the object and call the method. The stored procedure that we wrote to do this can be found below.
===========================================
CREATE PROCEDURE prcSendMSMQMessage
@vc_msmqpath varchar(255),
@vc_messagelabel varchar(255),
@vc_messagebody varchar(1000)
AS
DECLARE @int_msmqqueue INT
DECLARE @int_result INT
-- Create the SQLMSMQ.CSQLSendMessage Object.
EXECUTE @int_result = sp_OACreate 'SQLMSMQ.CSQLSendMessage', @int_msmqqueue OUT, 1
IF @int_result <> 0 GOTO ErrorHandler
-- Send the message using the Send method
EXECUTE @int_result = sp_OAMethod @int_msmqqueue, 'Send', NULL, @vc_msmqpath, @vc_messagelabel, @vc_messagebody
IF @int_result <> 0 GOTO ErrorHandler
GOTO DestroyObjects
ErrorHandler:
DECLARE @vc_source varchar(53), @vc_description VARCHAR(200)
EXECUTE sp_OAGetErrorInfo @int_msmqqueue, @vc_source OUT, @vc_description OUT, NULL, NULL
RAISERROR(@vc_description, 16, 1)
GOTO DestroyObjects
DestroyObjects:
-- Destroy the SQLMSMQ.CSQLSendMessage object.
EXECUTE @int_result = sp_OADestroy @int_msmqqueue
RETURN
==================================================
Now the obvious question is, why don't we just use the sp_OACreate method to instantiate the Message Queue objects and manipulate them directly. A good question that is, too. The reason for jumping through these hoops is one of data types. The Body property of the MSMQMessage object has a data type of variant. Unfortunately, SQL does not have such a data type. And trying to assign variables of any type to Body using the sp_OASetProperty method results in a 'The parameter is incorrect' error message. So we are reduced to creating the Visual Basic DLL component to act as a stub. A klude? Yes. But we're more concerned with results than elegance. Especially when the elegant way doesn't work.
作者: 阿罗 时间: 2003-9-21 01:20
由于我没有vb,是否请有条件的朋友传一个做好的activeX上来?
作者: 阿罗 时间: 2003-9-21 07:20
更进一步参考资料:在sql服务器里使用activeX
下个星期计划找个vb6来进行试验。将逐步充实这个帖子的内容。
作者: 阿罗 时间: 2003-9-21 07:21
[attach]1774[/attach]
这个是一个PDF文档,讲述如在SQL服务器里调用activeX组件。
[此贴子已经被作者于2003-9-21 23:42:44编辑过]
作者: 阿罗 时间: 2003-9-22 07:18
我的实验过程:共4张图。
1) 将做好的dll注册。
2) 创建一个存储过程
3) 在查询分析器里试验存储过程
4) 检查消息队列
[此贴子已经被作者于2003-9-21 23:43:20编辑过]
作者: 阿罗 时间: 2003-9-22 07:22
[attach]1782[/attach]
作者: 阿罗 时间: 2003-9-22 07:23
[attach]1783[/attach][attach]1784[/attach][attach]1785[/attach]
作者: 阿罗 时间: 2003-9-22 07:24
[attach]1786[/attach]
这个就是SQLMSMQ.dll
作者: 阿罗 时间: 2003-9-22 07:27
如果还是不清楚msmq到底有何作用,可以参看一下连接:
http://www.yesky.com/SoftChannel/72342371928637440/20030506/1667016.shtml
作者: 阿罗 时间: 2003-9-22 07:28
MSMQ技术文档:
http://www.microsoft.com/windows2000/technologies/communications/msmq/default.asp
作者: 阿罗 时间: 2003-9-22 07:33
标题: 张悦的文章抄录如下:
消息队列在VB.NET数据库开发中的应用
2003-05-06■张悦■yesky
===========================================
我们先简单的了解一下什么是消息队列(MSMQ)?消息队列是 Windows 2000(NT也有MSMQ,WIN95/98/me/xp不含消息队列服务但是支持客户端的运行)操作系统中通讯的基础,也是用于创建分布式、松散连接通讯应用程序的工具。这些应用程序可以通过不同种类的网络进行通讯,也可以与脱机的计算机通讯。消息队列分为用户创建队列和系统队列,用户队列分为:
· "公共队列"在整个可传递消息的"消息队列"网络中复制并传输,并且有可能由网络连接的所有站点访问。
· "专用队列"不在整个网络中发布。相反,它们仅在所驻留的本地计算机上可用。专用队列只能由知道队列的完整路径名或标签的应用程序访问。
· "管理队列"包含确认在给定"消息队列"网络中发送的消息回执的消息。指定希望 MessageQueue 组件使用的管理队列
· "响应队列"包含目标应用程序接收到消息时返回给发送应用程序的响应消息。指定希望 MessageQueue 组件使用的响应队列。
系统队列分为:
· "日记队列"可选地存储发送消息的副本和从队列中移除的消息副本。
· "死信队列"存储无法传递或已过期的消息的副本。
· "专用系统队列"是一系列存储系统执行消息处理操作所需的管理和通知消息的专用队列。
现在大家对消息队列有了简单的了解后,就该进入主题了。要使用msmq进行软件开发需要安装msmq。安装完后就该进入实际的开发阶段。先打开vs.net ide中的"服务起资源管理器"展开你想建立消息队列的计算机名,再展开"消息队列"右击它在弹出菜单中选择"新建"建立一个新的消息队列,并为它指定一个名字,这个名字可以随意。也可以通过编程来完成,代码如下:
system.Messaging.MessageQueue.Create(".\Private$\MyPrivateQueue")'建立专用队列
System.Messaging.MessageQueue.Create("myMachine\MyQueue")'建立公共队列
其实我认为使用那中方法并不重要,重要的是搞清楚专用队列和公共队列的差别(其他队列不是必须的)。在本例中是通过"服务器资源管理器"分别在服务器上建立了专用队列和公共队列。
程序功能:本程序分为两部分包括服务器程序(安装在sql server服务器上)和客户端程序,客户端的作用是用来编写t-sql语句并将t-sql语句放在消息中,并将消息发送到sql server服务器上的消息队列中去。服务器程序检查指定的消息队列当发现有新消息到达时,就开始执行消息中的内容,由于消息中的内容是t-sql语句所以服务器端实际上是执行对数据库的操作。
客户端程序:
public Sub client()
Dim tM As New System.Messaging.MessageQueue()
tM.Path = ".\Private$\jk" '"FORMATNAME
UBLIC=3d3dc813-c555-4fd3-8ce0-79d5b45e0d75"'与指定计算机中的消息队列建立连接,
Dim newMessage As New System.Messaging.Message(TextBox1.Text)'接受文本筐的t-sql语句
newMessage.Label = "This is the label"'消息名字,
tM.Send(newMessage)'发送消息
End Sub
服务端程序:
public Sub server()
Dim NewQueue As New System.Messaging.MessageQueue(".\Private$\jk")'"FORMATNAME
UBLIC=3d3dc813-c555-4fd3-8ce0-79d5b45e0d75"'与指定计算机中的消息队列建立连接,
Dim m As System.Messaging.Message
'查看消息队列中的消息
m = NewQueue.Receive
m.Formatter = New System.Messaging.XmlMessageFormatter(New String() {"System.String,mscorlib"})
Dim st As String
st = m.Body'消息队列中消息的消息内容。既sql语句
Dim con As New OleDb.OleDbConnection("输入自己的数据库连接字符串")
con.Open()
Dim com As New OleDb.OleDbCommand(st, con)'执行消息中的sql语句
com.ExecuteNonQuery()
con.Close()
End Sub
我为什么要使用消息队列来处理数据库的操作这个问题我一直没回答,现在我就来回答这个问题。在本程序中你会发现在sub client()中我并没连接数据库和请求数据,而是通过发消息来操作数据库的,这个好处是节省了两部分时间:
1、对数据库连解请求数据的时间。
2、从数据库返回数据的时间。
在很多情况下其实我们并不需要看见具体的数据就知道该怎么修改数据库中的数据。例如要删除张三的记录,就可以将一条简单的删除语句放入消息中,发给服务器让服务器程序去处理对数据的更改。
此外消息队列的另一个主要用途也就是当前erp软件中必不可少的,就是在断开连接时保存信息,当连接恢复时发送消息。消息在如下两种情况中无法迅速地传递到它们的队列:当队列驻留的计算机无法工作时,或当路由消息所需的域控制器无法工作时。"消息队列"可让您应对这些情况,使得在从网络上断开连接或必要的计算机或控制器无法工作时,仍可以继续发送消息。在这些情形下,消息暂时存储在本地计算机或传递路由上的某个计算机的队列中,直到完成传递所需的资源重新联机。
作者: 阿罗 时间: 2003-9-22 07:41
通过这两天寻找资料,觉得MSMQ的用处很大,远远超出上面提到的一些。通过我自己的实验,对于如何扩展SQL服务器的应用范围有了很好的概念性了解,对消息队列有了一些初步的认识。像这里以前讨论过的,过一段时间从工作场点向服务器传送数据,我想,MSMQ可以提供一个十分适合的、非常可靠的解决思路。希望各位朋友也来讨论切磋。
作者: 阿罗 时间: 2003-9-22 08:18
MSMQ3.0中增加了触发器(2.0版本现在也可以增加这个功能了。)
像张悦的那篇文章中,服务器端的程序,可以用MSMQ触发器来执行。而对于本论坛以前讨论的一个超市,工作站要定时将数据上报到服务器这么个问题,除了用MSMQ来解决这个思路以外,我想还可以在SQL服务器端用DTS来解决,这样,结合当时提出来的几种方案,就有多种候选办法。至于具体问题,还要看网络连接的情况、网络负荷、开发时间、预算、可靠性要求、安全性要求等等具体情况采用最好的解决办法。
作者: 阿罗 时间: 2003-9-23 20:18
[attach]1799[/attach]
MSMQ的FAQ。
作者: 阿罗 时间: 2003-9-24 19:49
在工作组模式下,向局域网内其他电脑发送消息,如果另外一台电脑没有上线,则消息会放在本地的发送队列中。如果另外一台电脑上线,则会马上送达。在域的情况下,则消息的发送和储存会更灵活。
[attach]1813[/attach]
作者: sxhmft 时间: 2003-11-5 19:01
太好了,能不能把您收集的资料给我发一份?在下先行谢过。E-MAIL:sxhmft@vip.sina.com
作者: 阿罗 时间: 2003-11-5 19:59
所有我找到的资料都在这个帖子里了。更详细的东西,需要去msdn,都是英文资料。也可以到M$的新闻组去提问。这就是我所有的秘诀。
作者: sxhmft 时间: 2003-11-5 21:08
好好!谢谢您。
欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) |
Powered by Discuz! X3.3 |