利用Socket監聽SqlServer數據庫的變化,並推送消息到客戶端

新建一個SQL CLR數據庫項目,來對數據庫的變化進行監聽,如:當有數據發生變化(增刪改), SQL CLR數據庫項目就會得到通知,此時咱們在開啓一個Socket,將數據庫變化的消息發送到IIS服務器,IIS服務器而後再發布出數據庫已發送變化的消息,此時鏈接到服務器的客戶端就會收到通知,就會根據服務器發來的表名,去決定是否須要從新獲取數據,已達到客戶端的數據是實時數據的效果:html

第一步:
 
監聽數據庫(Sqlserver等)C#

 

第二:
 
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;
using System.Web.Services;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Text;
using System.Collections.Generic;
using System.Runtime.Remoting.Contexts;
 
 
public partial class Triggers
{
 // 爲目標輸入現有表或視圖並取消對特性行的註釋
 [Microsoft.SqlServer.Server.SqlTrigger(Name = "Trigger1", Target = "Users", Event = "AFTER INSERT, UPDATE")]
 public static void Trigger1()
 {
 
 SqlContext.Pipe.Send("hehuajun");
 List socketPool = new List();
 
 bool firstTime = true;
 
 SqlTriggerContext triggContext = SqlContext.TriggerContext;
 SqlParameter userName = new SqlParameter("@username", System.Data.SqlDbType.NVarChar);
 
 if (triggContext.TriggerAction == TriggerAction.Insert)
 {
 using (SqlConnection conn = new SqlConnection("context connection=true"))
 {
 conn.Open();
 SqlCommand sqlComm = new SqlCommand();
 SqlPipe sqlP = SqlContext.Pipe;
 
 sqlComm.Connection = conn;
 sqlComm.CommandText = "SELECT UserName from INSERTED";
 userName.Value = sqlComm.ExecuteScalar().ToString();
 sqlComm.CommandText = "INSERT UsersAudit(UserName) VALUES('" + userName + "')";
 sqlP.Send(sqlComm.CommandText);
 sqlP.ExecuteAndSend(sqlComm);
 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.10.11"), 4502); //填寫本身電腦的IP或者其餘電腦的IP,若是是其餘電腦IP的話需將ConsoleApplication_socketServer工程放在對應的電腦上。
 SqlServerProjectDemo.TableNotifyProtocol p = new SqlServerProjectDemo.TableNotifyProtocol();
 p.TableName = "Users";
 p.OperatorOnTable = "Update";
 socket.Connect(ipep);
 socket.Send(p.TableNotifyProtocolToBytes());
 socket.Close();
 }
 }
 }
 
 //static Socket serverSocket;
 
 // static Socket clientSocket;
 
 // static Thread thread;
 
 //public static void StartSocket()
 //{
 
 // IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 4530);
 
 // serverSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 
 // serverSocket.Bind(ipep);
 
 // serverSocket.Listen(10);
 
 // while (true)
 // {
 // Socket s = serverSocket.Accept();
 // socketPool.Add(s);
 // // clientSocket = s;
 // // thread = new Thread(new ThreadStart(doWork));
 // thread = new Thread(new ThreadStart(() =>
 // {
 // doWork(s, ASCIIEncoding.ASCII.GetBytes("1"));
 // }));
 // thread.Start();
 
 // }
 //}
 
 
 //public static void doWork(Socket s, byte[] buffer)
 //{
 // // Socket s = clientSocket;//客戶端信息
 // IPEndPoint ipEndPoint = (IPEndPoint)s.RemoteEndPoint;
 
 // String address = ipEndPoint.Address.ToString();
 
 // String port = ipEndPoint.Port.ToString();
 
 // Console.WriteLine(address + ":" + port + " 鏈接過來了");
 
 // Byte[] inBuffer = new Byte[1024];
 
 // Byte[] outBuffer = new Byte[1024];
 
 // String inBufferStr;
 
 // String outBufferStr;
 
 // try
 // {
 
 // while (true)
 // {
 
 // // s.Receive(inBuffer, 1024, SocketFlags.None);//若是接收的消息爲空 阻塞 當前循環
 
 // // inBufferStr = Encoding.ASCII.GetString(inBuffer);
 
 // // Console.WriteLine(address + ":" + port + "說:");
 
 // // Console.WriteLine(inBufferStr);
 
 // //// outBufferStr = Console.ReadLine();
 
 // // //outBufferStr = p.TableNotifyProtocolToBytes();
 // // //outBuffer = Encoding.ASCII.GetBytes(outBufferStr);
 // // outBuffer = p.TableNotifyProtocolToBytes();
 // s.Send(buffer, buffer.Length, SocketFlags.None);
 // }
 // }
 
 // catch
 // {
 // Console.WriteLine("客戶端已關閉!");
 // }
 
 //}
 
 public bool IsEMailAddress(string s)
 {
 return Regex.IsMatch(s, "^([\\w-]+\\.)*?[\\w-]+@[\\w-]+\\.([\\w-]+\\.)*?[\\w]+$");
 }
 
}
 
 
第三步:爲了能使用Socket,須要爲程序集簽名:
監聽數據庫(Sqlserver等)C#

第四步:
 
在數據庫中執行:
 
USE master
 CREATE ASYMMETRIC KEY SQLCLRTestKey1
 
 FROM EXECUTABLE FILE = 'C:\SqlServerProjectDemo.dll'
 
 
CREATE LOGIN SQLCLRTestLogin FROM ASYMMETRIC KEY SQLCLRTestKey
 GRANT EXTERNAL ACCESS ASSEMBLY TO SQLCLRTestLogin;
GO
 
注意:最好不要直接使用debug目錄,能夠將你的項目生成的dll拷貝到另外的地方。如: C:\SqlServerProjectDemo.dll
 
F5啓動部署:
成功後:
在數據庫中執行
 
insert into Users(UserName,Pass) values('admin','admin')
 
Update Users set UserName='哈哈哈' where UserName='admin'
 
而後在你的Socket端的服務器上就會收到 你發送過去的數據。
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace SqlServerProjectDemo
{
 
 public struct TableNotifyProtocol
 {
 public string TableName;
 public string OperatorOnTable;
 public byte[] TableNotifyProtocolToBytes()
 {
 string s = "TableName=" + TableName + "|" + "OperatorOnTable=" + OperatorOnTable+"|";
 
 byte[] bTableName = ASCIIEncoding.ASCII.GetBytes(TableName);
 byte[] bOperatorOnTable = ASCIIEncoding.ASCII.GetBytes(OperatorOnTable);
 //byte[] buffer = new byte[bTableName.Length + bOperatorOnTable.Length];
 //ASCIIEncoding.ASCII.GetBytes(TableName, 0, bTableName.Length, buffer, 0);
 //ASCIIEncoding.ASCII.GetBytes(OperatorOnTable, 0, bOperatorOnTable.Length, buffer, bTableName.Length);
 
 byte[] buffer = ASCIIEncoding.ASCII.GetBytes(s);
 
 return buffer;
 }
 public TableNotifyProtocol GetModel(byte[] buffer)
 {
 string s = ASCIIEncoding.ASCII.GetString(buffer);
 TableNotifyProtocol model = new TableNotifyProtocol();
 model.OperatorOnTable = GetString(s, "OperatorOnTable");
 model.TableName = GetString(s, "TableName");
 return model;
 }
 private string GetString(string s,string key)
 {
 string tmp = s.Substring(s.IndexOf(key) + key.Length + 1);
 string v=tmp.Substring(0,tmp.IndexOf("|"));
 return v;
 }
 }
 
 
}
相關文章
相關標籤/搜索