近日开发一个系统,与莫懒惰单位合作,商量接口时考虑到由自己定义的报文进行通信,必定导致相当长的联调时间,而且近日诸项目缠身,没有足够的时间陪这种懒惰的单位玩,于是一时冲动就说开发一个数据库让他写入数据库就算了。但是问题也就出现了描述如下:
该系统乃C/S架构当懒惰单位发送一个信息过来Server端,然后Server分析处理再向其中一个客户端发送信息,可以简化为这种模型
懒惰单位-----推送消息----->Server处理-----推送消息----->客户端接收
使用数据库(SQL)
懒惰单位-----推送消息----->这一步骤是完成了,但是存入数据库的时候怎么马上通知Server进行处理呢,其中我想过就是不停的轮讯,例如每一秒查一下表,但是这样的话,日积月累该表必定很大,所以导致每次select 都是很长的时间,即使怎么优化地使用索引也未必能很好地解决问题。
如果每隔一段时间将表的部分数据移出(删除/转移到其他表)也是一个办法,但是由于该系统不能停,而且要求实时性很高,依靠轮询这种拉消息的方法始终是很难解决问题的。
该问题困扰了好几日,后来借鉴编程 的事件处理模式,考虑到给表加上触发器,但是触发器怎么向应用程序通信呢,而且怎么得到新增加的记录呢?由此发散想一下,可以用存储过程的啊,CLR存储过程,只要别人调用我这个存储过程,我在插入的时候顺便向应用程序发信号就可以啦,但是怎么发呢,后来想到可以写个UDP的发送程序向本机发的嘛,这样就变成了推送消息了啊
代码如下:
using
System;
using
System.Data;
using
System.Data.SqlClient;
using
System.Data.SqlTypes;
using
Microsoft.SqlServer.Server;
using
System.Net;
using
System.Net.Sockets;
using
System.Text;
public
partial
class
StoredProcedures
...
{ private static readonly string SP_Call = "Ring"; [Microsoft.SqlServer.Server.SqlProcedure] public static void CLR_Ring(string from , string to) ...{ SqlCommand myCommand = new SqlCommand(); myCommand.CommandType = CommandType.StoredProcedure; myCommand.CommandText = SP_Call; myCommand.Parameters.AddWithValue("@FromNumber", from); myCommand.Parameters.AddWithValue("@ToNumber", to); SqlPipe myPipe = SqlContext.Pipe; myPipe.ExecuteAndSend(myCommand); UdpClient Client = new UdpClient(); string toSend = "message:"+from + "|" + to+" "; byte[] bytes = UnicodeEncoding.Unicode.GetBytes(toSend); Client.Connect("localhost", 3390); Client.Send( bytes,bytes.Length ); Client.Close(); }}
;
最后设定程序集的安全级别为不安全,程序集所有者为dbo