sql server主動推送客戶端更新數據


小談需求:

最近工作上接到一個需求,做一個web展示數據的報表,最好能實時更新,不限制所用技術。

第一個問題:web服務器推送給瀏覽器新數據,一開始我想到的最快的最簡單的方法就是 在web頁面上js輪詢了。因為我們的數據更新頻率並不快。 后來覺得這種辦法有點太土了。 或許長輪詢更有效。  當然長輪詢的技術很多了。 java 的dwr,c#的 signalr。c#還可以同過異步請求來自己寫長輪詢。

遇到的第二個問題,就是數據庫如何通知web服務器更新數據,下面便是sql server2008的推送了,通過sql server的觸發器,當數據表有變化時(增,刪,改)就通過tcp請求服務器,服務器會在啟動后開啟端口一直監聽,隨時等待通信請求。當收到請求后,就從數據庫讀取新數據,推送給瀏覽器。整體大概就這樣。

下面是數據庫通知服務器。這是一個 winform的demo ,winfom就相當於我們展示數據的服務器了。

最后demo圖:

現在我插入一條數據:

然后再看那個客戶端:

剛插入的數據已經出現了哦。

客戶端代碼:

winform:

程序啟動后,開啟端口監聽,如果有收到通信,則通知 dataview更新數據。

using System;
02 using System.Collections.Generic;
03 using System.ComponentModel;
04 using System.Data;
05 using System.Data.SqlClient;
06 using System.Drawing;
07 using System.Linq;
08 using System.Net;
09 using System.Net.Sockets;
10 using System.Text;
11 using System.Windows.Forms;
12 using System.Threading;
13  
14 namespace sql_dependency
15 {
16     public partial class Form1 : Form
17     {
18         public Form1()
19         {
20             InitializeComponent();
21         }
22  
23         System.Data.SqlClient.SqlConnection conn = null;
24         string _connstr = "Data Source = 10.6.154.251; database=Temp;user id=sa;pwd=MOcyou0543_";
25         System.Data.SqlClient.SqlCommand command = null;
26  
27         private void Form1_Load(object sender, EventArgs e)
28         {
29             conn = new System.Data.SqlClient.SqlConnection(_connstr);
30             command = conn.CreateCommand();
31             command.CommandText = "select [A],[B],[C] From [Temp].[dbo].[Simple]";
32             SqlDependency.Start(_connstr);//啟動
33             Thread t = new Thread(new ThreadStart(GetData));
34             t.Start();
35         }
36  
37  
38         private void GetData()
39         {
40  
41             SetData();
42             IPAddress localAddr = IPAddress.Parse("127.0.0.1");
43             TcpListener tcplistener = new TcpListener(localAddr, 10010);
44             tcplistener.Start();
45             byte[] btServerReceive = new byte[2048];
46             string strServerReceive = string.Empty;
47             while (true)
48             {
49                 TcpClient tcp = tcplistener.AcceptTcpClient();
50                 Console.WriteLine("Connected!");
51                 NetworkStream ns = tcp.GetStream();
52                 int intReceiveLength = ns.Read(btServerReceive, 0, btServerReceive.Length);
53                 strServerReceive = Encoding.ASCII.GetString(btServerReceive, 0, intReceiveLength);
54  
55                 SetData();
56                 tcp.Close();
57             }
58  
59         }
60         private delegate void ChangeDataView();
61         private void SetData()
62         {
63             if (this.InvokeRequired)
64             {
65                 this.Invoke(new ChangeDataView(SetData));
66             }
67             else
68             {
69                 using (SqlDataAdapter adapter = new SqlDataAdapter(command)) //查詢數據
70                 {
71                     System.Data.DataSet ds = new DataSet();
72                     adapter.Fill(ds, 0, 100, "Simple");
73                     dataGridView1.DataSource = ds.Tables["Simple"];
74                 }
75  
76             }
77         }
78  
79  
80  
81         private void Form1_Closed(object sender, FormClosedEventArgs e)
82         {
83             //清理現場
84             SqlDependency.Stop(_connstr);
85             conn.Close();
86             conn.Dispose();
87         }
88  
89  
90     }
91

}

 

數據庫與clr集成,編寫寫dll:SqlDependency.dll,sql server將在可編程性中加載此dll,

01 using System;
02 using System.IO;
03 using System.Net;
04 using System.Net.Sockets;
05 using Microsoft.SqlServer.Server;
06  
07 using System.Net.Sockets;
08 namespace SqlDependency
09 {
10     public class Program
11     {
12  
13         [SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.Read)]
14         public static String WriteStringToFile(String FileFullPath, String Contend)
15         {
16  
17             FileInfo Fi = new FileInfo(FileFullPath);
18             if (!Fi.Directory.Exists)
19             {
20                 Fi.Directory.Create();
21             }
22  
23             using (StreamWriter rw = File.CreateText(FileFullPath))
24             {
25  
26                 rw.WriteLine(Contend);
27                 TcpClient tcpClient = new TcpClient();
28  
29                 try
30                 {
31                     if (tcpClient == null)
32                     {
33                         tcpClient = new TcpClient();
34                         tcpClient.ReceiveTimeout = 20000;
35                     }
36                     if (tcpClient.Connected == false)
37                     {
38                         System.Net.IPAddress address = System.Net.IPAddress.Parse(Contend);
39                         System.Net.IPHostEntry ipInfor = System.Net.Dns.GetHostByAddress(address);
40                         string hostName = ipInfor.HostName;
41                         IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10010);
42                         tcpClient.Connect(serverEndPoint);
43                         rw.Write(hostName);
44                     }
45                     rw.Write("連接成功,先發送指令");
46                     // Translate the passed message into ASCII and store it as a Byte array.
47                     Byte[] data = System.Text.Encoding.ASCII.GetBytes("new data!");
48  
49                     NetworkStream stream = tcpClient.GetStream();
50  
51                     // Send the message to the connected TcpServer.
52                     stream.Write(data, 0, data.Length);
53                     stream.Close();
54                  
55                 }
56                 catch (Exception e)
57                 {
58                     rw.Write(e.Message);
59                 }
60                 tcpClient.Close(); 
61                 rw.Flush();
62                 rw.Close();
63                 return "";
64             }
65         }
66     }
67 }

接下來,便開始配置sql server啦:

首先開啟sql server的clr支持:

1 開啟數據庫CLR 支持
2 --exec sp_configure 'clr enabled', 1;
3 --開始數據的驗證
4 alter database dbname set TRUSTWORTHY on;
5 RECONFIGURE

接着在sql server 2008中,新建查詢窗口。加載剛才編寫的dll SqlDependency.dll,並注冊方法,然后寫觸發器,當表數據有變化時,觸發函數。:

 

01 use Temp;--數據庫名
02 create assembly SqlDependency FROM 'D:\SqlDependency.dll'--程序集名稱和地址
03 WITH PERMISSION_SET = UNSAFE
04 GO
05  
06 --方法名寫正確,為程序集中的方法名,注意參數個數
07 create function WriteStringToFile(@FileFullName as nvarchar(max),  @FileContend AS  nvarchar(max))
08 returns nvarchar(max)
09 with returns null on null input
10 external name [SqlDependency].[SqlDependency.Program].[WriteStringToFile]
11 GO
12  
13 --編寫觸發器,傳遞參數以及
14 CREATE TRIGGER [dbo].[UserTableChangedEvent] on [dbo].[Simple] 
15     FOR INSERT, DELETE, UPDATE 
16        
17 AS 
18     BEGIN 
19     DECLARE @Contend AS VARCHAR(100) 
20     DECLARE @FileName AS VARCHAR(MAX
21         SET @FileName ='D:\\MSG\\'+CONVERT(varchar(12) , getdate(), 112 )+'\\'+ convert(nvarchar(50), NEWID())+'.TXT' 
22           
23        SET @Contend = '127.0.0.1'
24        Select dbo.WriteStringToFile(@FileName, @Contend) 
25                    
26     END 
27   GO

注意,我的應用程序和 數據庫在一台服務器上,所以地址都是127.0.0.1.可跟據實際填寫正確地址。

再次在sql server中新建一個查詢窗口,插入語句,進行測試吧。

如果過程中有問題,需要更新程序,方便地刪除之上所創建的幾個東

1 drop TRIGGER [dbo].[UserTableChangedEvent]
2 drop function WriteStringToFile
3 drop assembly SqlDependency

 

抄送:開源中國  http://my.oschina.net/u/867090/blog/122146


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM