sql server主动推送客户端更新数据
小谈需求:
最近工作上接到一个需求,做一个web展示数据的报表,最好能实时更新,不限制所用技术。
第一个问题:web服务器推送给浏览器新数据,一开始我想到的最快的最简单的方法就是 在web页面上js轮询了。因为我们的数据更新频率并不快。 后来觉得这种办法有点太土了。 或许长轮询更有效。 当然长轮询的技术很多了。 java 的dwr,c#的 signalr。c#还可以同过异步请求来自己写长轮询。
遇到的第二个问题,就是数据库如何通知web服务器更新数据,下面便是sql server2008的推送了,通过sql server的触发器,当数据表有变化时(增,删,改)就通过tcp请求服务器,服务器会在启动后开启端口一直监听,随时等待通信请求。当收到请求后,就从数据库读取新数据,推送给浏览器。整体大概就这样。
下面是数据库通知服务器。这是一个 winform的demo ,winfom就相当于我们展示数据的服务器了。
最后demo图:

现在我插入一条数据:

然后再看那个客户端:

刚插入的数据已经出现了哦。
客户端代码:
winform:
程序启动后,开启端口监听,如果有收到通信,则通知 dataview更新数据。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Windows.Forms;using System.Threading;namespace sql_dependency{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } System.Data.SqlClient.SqlConnection conn = null; string _connstr = "Data Source = 10.6.154.251; database=Temp;user id=sa;pwd=MOcyou0543_"; System.Data.SqlClient.SqlCommand command = null; private void Form1_Load(object sender, EventArgs e) { conn = new System.Data.SqlClient.SqlConnection(_connstr); command = conn.CreateCommand(); command.CommandText = "select [A],[B],[C] From [Temp].[dbo].[Simple]"; SqlDependency.Start(_connstr);//启动 Thread t = new Thread(new ThreadStart(GetData)); t.Start(); } private void GetData() { SetData(); IPAddress localAddr = IPAddress.Parse("127.0.0.1"); TcpListener tcplistener = new TcpListener(localAddr, 10010); tcplistener.Start(); byte[] btServerReceive = new byte[2048]; string strServerReceive = string.Empty; while (true) { TcpClient tcp = tcplistener.AcceptTcpClient(); Console.WriteLine("Connected!"); NetworkStream ns = tcp.GetStream(); int intReceiveLength = ns.Read(btServerReceive, 0, btServerReceive.Length); strServerReceive = Encoding.ASCII.GetString(btServerReceive, 0, intReceiveLength); SetData(); tcp.Close(); } } private delegate void ChangeDataView(); private void SetData() { if (this.InvokeRequired) { this.Invoke(new ChangeDataView(SetData)); } else { using (SqlDataAdapter adapter = new SqlDataAdapter(command)) //查询数据 { System.Data.DataSet ds = new DataSet(); adapter.Fill(ds, 0, 100, "Simple"); dataGridView1.DataSource = ds.Tables["Simple"]; } } } private void Form1_Closed(object sender, FormClosedEventArgs e) { //清理现场 SqlDependency.Stop(_connstr); conn.Close(); conn.Dispose(); } }} |
数据库与clr集成,编写写dll:SqlDependency.dll,sql server将在可编程性中加载此dll,
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
using System;using System.IO;using System.Net;using System.Net.Sockets;using Microsoft.SqlServer.Server;using System.Net.Sockets;namespace SqlDependency{ public class Program { [SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.Read)] public static String WriteStringToFile(String FileFullPath, String Contend) { FileInfo Fi = new FileInfo(FileFullPath); if (!Fi.Directory.Exists) { Fi.Directory.Create(); } using (StreamWriter rw = File.CreateText(FileFullPath)) { rw.WriteLine(Contend); TcpClient tcpClient = new TcpClient(); try { if (tcpClient == null) { tcpClient = new TcpClient(); tcpClient.ReceiveTimeout = 20000; } if (tcpClient.Connected == false) { System.Net.IPAddress address = System.Net.IPAddress.Parse(Contend); System.Net.IPHostEntry ipInfor = System.Net.Dns.GetHostByAddress(address); string hostName = ipInfor.HostName; IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10010); tcpClient.Connect(serverEndPoint); rw.Write(hostName); } rw.Write("连接成功,先发送指令"); // Translate the passed message into ASCII and store it as a Byte array. Byte[] data = System.Text.Encoding.ASCII.GetBytes("new data!"); NetworkStream stream = tcpClient.GetStream(); // Send the message to the connected TcpServer. stream.Write(data, 0, data.Length); stream.Close(); } catch (Exception e) { rw.Write(e.Message); } tcpClient.Close(); rw.Flush(); rw.Close(); return ""; } } }} |
接下来,便开始配置sql server啦:
首先开启sql server的clr支持:
|
1
2
3
4
5
|
开启数据库CLR 支持--exec sp_configure 'clr enabled', 1;--开始数据的验证alter database dbname set TRUSTWORTHY on;RECONFIGURE |
接着在sql server 2008中,新建查询窗口。加载刚才编写的dll SqlDependency.dll,并注册方法,然后写触发器,当表数据有变化时,触发函数。:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
use Temp;--数据库名create assembly SqlDependency FROM 'D:\SqlDependency.dll'--程序集名称和地址WITH PERMISSION_SET = UNSAFEGO--方法名写正确,为程序集中的方法名,注意参数个数create function WriteStringToFile(@FileFullName as nvarchar(max), @FileContend AS nvarchar(max))returns nvarchar(max)with returns null on null inputexternal name [SqlDependency].[SqlDependency.Program].[WriteStringToFile]GO--编写触发器,传递参数以及CREATE TRIGGER [dbo].[UserTableChangedEvent] on [dbo].[Simple] FOR INSERT, DELETE, UPDATE AS BEGIN DECLARE @Contend AS VARCHAR(100) DECLARE @FileName AS VARCHAR(MAX) SET @FileName ='D:\\MSG\\'+CONVERT(varchar(12) , getdate(), 112 )+'\\'+ convert(nvarchar(50), NEWID())+'.TXT' SET @Contend = '127.0.0.1'; Select dbo.WriteStringToFile(@FileName, @Contend) END GO |
注意,我的应用程序和 数据库在一台服务器上,所以地址都是127.0.0.1.可跟据实际填写正确地址。
再次在sql server中新建一个查询窗口,插入语句,进行测试吧。
如果过程中有问题,需要更新程序,方便地删除之上所创建的几个东东:
|
1
2
3
|
drop TRIGGER [dbo].[UserTableChangedEvent] drop function WriteStringToFiledrop assembly SqlDependency |
之后将尝试在web 结合 signal实现实时推送数据给web页面。等待下篇。
sql server主动推送客户端更新数据的更多相关文章
- DT7.0主动推送当天高质量图片数据到熊掌号展现
<?php /* 百度当天主动推送熊掌功能 作者:68喜科技 用于:DT7.0 功能模块:优质内容推送熊掌*出图内容当天推送 */ //引入全局变量函数 defined('IN_DESTOON' ...
- SQL Server ->> DISABLE索引后插入更新数据再REBUILD索引 和 保留索引直接插入更新数据的性能差异
之前对于“DISABLE索引后插入更新数据再REBUILD索引 和 保留索引直接插入更新数据的性能差异”这两种方法一直认为其实应该差不多,因为无论如何索引最后都需要被维护,只不过是个时间顺序先后的问题 ...
- SQL Server通过创建临时表遍历更新数据
前言: 前段时间新项目上线为了赶进度很多模块的功能都没有经过详细的测试导致了生成环境中的数据和实际数据对不上,因此需要自己手写一个数据库脚本来更新下之前的数据.(线上数据库用是SQL Server20 ...
- SpringBoot2.x服务器端主动推送技术
一.服务端推送常用技术介绍 服务端主流推送技术:websocket.SSE等 1.客户端轮询:ajax定时拉取后台数据 js setInterval定时函数 + ajax异步加载 定时向服务 ...
- 【SpringBoot】服务器端主动推送SSE技术讲解
=====================16.高级篇幅之SpringBoot2.0服务器端主动推送SSE技术讲解 ============================ 1.服务端推送常用技术介绍 ...
- 织梦CMS5.7主动推送二次开发
今天一个朋友叫我写个织梦的百度主动推送插件,实现的功能是:每发表或者更新一篇文章,都会触动主动推送,达到资源最新提交给百度进行抓取. 案例站点:奇迹私服 第一步:登入FTP,在/后台的文件夹/arti ...
- server端推送消息机制
推送技术相关请参加WIKI: https://zh.wikipedia.org/wiki/%E6%8E%A8%E9%80%81%E6%8A%80%E6%9C%AF 场景: 监控系统:后台硬件温度.电压 ...
- SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪
来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html 本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...
- SQL Server 之 在数据库之间进行数据导入导出
1.同一服务器上数据库之间进行数据导入导出 (1).使用 SELECT INTO 导出数据 在SQL Server中使用最广泛的就是通过SELECT INTO语句导出数据,SELECT INTO语句同 ...
随机推荐
- bzoj3790
观察发现,这道题目其实就相当于一个最小区间覆盖问题这里的区间是指以每个点为中心的最长回文串很久没写manacher,有点感动不得不说manacher是一个非常好的算法 ..] of char; c,l ...
- 【转】linux(Ubuntu)配置svn仓库,搭建svn服务器
原文网址:http://blog.1v2d.com/322.html 在家里搞了好久,终于搞出来,并且在线上已经成功搭建成功,在这感谢一个博主的文章,本篇文章也主要是转载他的内容,写的非常好,而且非常 ...
- “ORA-12545: 因目标主机或对象不存在,连接失败”怎么办?
大概知道是因为主机名或者IP地址的原因引起的,但是不知道究竟,就去百度上查了查,然后就根据几种答案做出了以下就该: 1.E:\oracle\product\10.2.0\db_1\NETWORK\AD ...
- C#调用C++动态库(dll)
在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用re ...
- Hadoop的文件读写操作流程
以下主要讲解了Hadoop的文件读写操作流程: 读文件 读文件时内部工作机制参看下图: 客户端通过调用FileSystem对象(对应于HDFS文件系统,调用DistributedFileSystem对 ...
- 利用腾讯企业邮箱开放API获取账户未读邮件数初探
公司一直使用腾讯提供的免费企业邮箱服务,今天用管理员帐户登录后发现,原来现在腾讯的企业邮箱也开放了部分API 你可以通过开放接口实现以下功能: 数据同步 数据同步可以帮助你同步部门成员信息,你还可以创 ...
- 折腾iPhone的生活——AirDrop的使用
AirDrop是iOS一个非常大的亮点,其实说是这么说了,但是事实上AirDrop并没有想象中那么好用. AirDrop就是一个用于无线传输文件的方式,实质性跟蓝牙没有太大区别,但是比蓝牙好用,有点像 ...
- OpenFlow能解决私有云网络VLAN问题么
本文转载自:http://network.51cto.com/art/201202/314310.htm 在关于私有云网络的文章中,我们首先探讨了物理网络是否影响私有云.本文我们将讨论如何通过软件定义 ...
- 部署war包到Tomcat
1. 开发给到一个war包,假设叫 a-b-c.war. 2. 打开Tomcat安装路径 ,假设是“D:\Tomcat\apache-tomcat-7.0.68”,然后进入到 webapps文件夹. ...
- DataTable无法使用AsEnumerable ()的解决办法
本人定义了DataSet后将表1赋给datatable,在写linq时调用datatable.asenumerable(),但报datatable不包含asenumerable的定义,求高手指点.Sy ...