sqlserver使用clr调用ajax,在数据库内请求外部链接

sqlserver使用clr调用ajax,在数据库内请求外部链接

2019年09月11日 14:52:48 文盲老顾 阅读数 12 文章标签: clrajax外部链接sql函数 更多

分类专栏: .net clr sql

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/superwfei/article/details/100735416

第一步:使用vs新建一个类库项目,编写clr程序集


 
  1. using Microsoft.SqlServer.Server;

  2. using System;

  3. using System.Collections;

  4. using System.Data.SqlTypes;

  5. using System.Diagnostics.CodeAnalysis;

  6. using System.IO;

  7. using System.IO.Compression;

  8. using System.Net;

  9. using System.Text;

  10. using System.Text.RegularExpressions;

  11.  
  12. internal class AjaxResult

  13. {

  14. private int _statusCode;

  15. private string _url;

  16. private string _html;

  17. public string Url

  18. {

  19. get

  20. {

  21. return _url;

  22. }

  23. }

  24. public string Html

  25. {

  26. get

  27. {

  28. return _html;

  29. }

  30. }

  31. public int StatusCode

  32. {

  33. get

  34. {

  35. return _statusCode;

  36. }

  37. }

  38. public AjaxResult(string url, string html, int statusCode)

  39. {

  40. _url = url;

  41. _html = html;

  42. _statusCode = statusCode;

  43. }

  44. }

  45. internal class AjaxIterator : IEnumerable

  46. {

  47. private string _url;

  48. private string _method;

  49. private string _arguments;

  50. public AjaxIterator(string url, string method, string arguments)

  51. {

  52. _url = url;

  53. _method = method;

  54. _arguments = arguments;

  55. }

  56. public IEnumerator GetEnumerator()

  57. {

  58. Ajax ajax = new Ajax();

  59. ajax.Http(_url, _method.ToLower(), _arguments);

  60. string url = ajax.CurrentUrl;

  61. string html = ajax.Result;

  62. int statusCode = (int)ajax.StatusCode;

  63. yield return new AjaxResult(url, html, statusCode);

  64. }

  65. }

  66. public static partial class ajax

  67. {

  68. [SqlFunction(FillRowMethodName = "FillAjaxRow", TableDefinition = "url nvarchar(500),html nvarchar(max),statusCode int")]

  69. public static IEnumerable Http(SqlString url, SqlString method, SqlString arguments)

  70. {

  71. return new AjaxIterator(url.Value, method.Value, arguments.Value);

  72. }

  73. [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters")]

  74. public static void FillAjaxRow(object data, out SqlString url, out SqlString html, out SqlInt32 statusCode)

  75. {

  76. AjaxResult node = (AjaxResult)data;

  77. url = new SqlString(node.Url);

  78. html = new SqlString(node.Html);

  79. statusCode = new SqlInt32(node.StatusCode);

  80. }

  81. }

  82. public class Ajax

  83. {

  84. private string _url = string.Empty;

  85. private string _result = "";

  86. private HttpStatusCode hsc = HttpStatusCode.OK;

  87. public string CurrentUrl

  88. {

  89. get

  90. {

  91. return _url;

  92. }

  93. }

  94. public string Result

  95. {

  96. get

  97. {

  98. return _result;

  99. }

  100. }

  101. public HttpStatusCode StatusCode

  102. {

  103. get

  104. {

  105. return hsc;

  106. }

  107. }

  108. private Encoding GetEncoding(string html)

  109. {

  110. if (Regex.IsMatch(html, @"(?<=<meta(?!\w)[^<>]*?)charset\s*=", RegexOptions.IgnoreCase))

  111. {

  112. string c = Regex.Match(html, @"(?<=<meta(?!\w)[^<>]*?charset\s*=\s*['""]?(?!['""]))\w[^\s'""/<>]*", RegexOptions.IgnoreCase).Value;

  113. try

  114. {

  115. Encoding en = Encoding.GetEncoding(Regex.Match(html, @"(?<=<meta(?!\w)[^<>]*?charset\s*=\s*['""]?(?!['""]))\w[^\s'""/<>]*", RegexOptions.IgnoreCase).Value);

  116. return en;

  117. }

  118. catch

  119. {

  120. return null;

  121. }

  122. }

  123. else

  124. {

  125. return null;

  126. }

  127. }

  128. public void Http(string url, string method, string QueryString)

  129. {

  130. string full_url = (("get" == method) ? ((QueryString.Length > 0) ? ((url.IndexOf("?") > 0) ? (url + "&" + QueryString) : (url + "?" + QueryString)) : url) : url);

  131. ServicePointManager.Expect100Continue = false;

  132. ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;

  133. string html = "";

  134. HttpWebRequest http = (HttpWebRequest)WebRequest.Create(full_url);

  135. http.AllowAutoRedirect = true;

  136. http.UserAgent = "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0";

  137. http.Accept = "*/*";

  138. http.KeepAlive = false;

  139. http.Headers.Add("Accept-Encoding", "gzip, deflate");

  140. _url = url;

  141. if (method == "post")

  142. {

  143. http.Method = "POST";

  144. http.Accept = "application/json, text/javascript, */*";

  145. http.KeepAlive = true;

  146. byte[] pd = null;

  147. pd = new UTF8Encoding().GetBytes(QueryString);

  148. try

  149. {

  150. http.ContentType = "application/x-www-form-urlencoded";

  151. http.ContentLength = pd.Length;

  152. Stream ps = http.GetRequestStream();

  153. ps.Write(pd, 0, pd.Length);

  154. ps.Close();

  155. ps.Dispose();

  156. }

  157. catch (Exception ex)

  158. {

  159. _result = ex.Message;

  160. hsc = HttpStatusCode.BadRequest;

  161. return;

  162. }

  163. }

  164. try

  165. {

  166. HttpWebResponse hwr = (HttpWebResponse)http.GetResponse();

  167. hsc = hwr.StatusCode;

  168. Stream s = hwr.GetResponseStream();

  169. MemoryStream ms = new MemoryStream();

  170. string contentType = "normal";

  171. if (hwr.Headers.GetValues("Content-Encoding") != null)

  172. {

  173. string[] encd = hwr.Headers.GetValues("Content-Encoding");

  174. for (int i = 0; i < encd.Length; i++)

  175. {

  176. if (encd[i] == "gzip")

  177. {

  178. contentType = "gzip";

  179. break;

  180. }

  181. if (encd[i] == "deflate")

  182. {

  183. contentType = "deflate";

  184. break;

  185. }

  186. }

  187. }

  188. switch (contentType)

  189. {

  190. case "deflate":

  191. DeflateStream ds = new DeflateStream(s, CompressionMode.Decompress);

  192. ds.CopyTo(ms);

  193. ds.Close();

  194. ds.Dispose();

  195. break;

  196. case "gzip":

  197. GZipStream g = new GZipStream(s, CompressionMode.Decompress);

  198. g.CopyTo(ms);

  199. g.Close();

  200. g.Dispose();

  201. break;

  202. default:

  203. s.CopyTo(ms);

  204. break;

  205. }

  206. s.Close();

  207. s.Dispose();

  208. byte[] bt = ms.ToArray();

  209. ms.Close();

  210. ms.Dispose();

  211. html = Encoding.UTF8.GetString(bt);

  212. Encoding en_test = GetEncoding(html);

  213. if (en_test != null && en_test != Encoding.UTF8)

  214. {

  215. html = en_test.GetString(bt);

  216. }

  217. _result = html;

  218. hwr.Close();

  219. }

  220. catch (WebException ex)

  221. {

  222. if (ex.Response == null)

  223. {

  224. hsc = HttpStatusCode.BadRequest;

  225. _result = ex.Message;

  226. return;

  227. }

  228. hsc = ((HttpWebResponse)ex.Response).StatusCode;

  229. _result = ex.Message;

  230. }

  231. }

  232. }

在这个类库随便命名了,编写好之后生成或发布

第二步:导入程序集

在sql server management studio里,找到你要操作的数据库 -> 可编程性 -> 程序集 -> 鼠标右键 -> 新建程序集

弹出上图所示的对话框,点浏览选择之前生成的dll文件

第三步:创建一个自定义函数,调用clr程序集


 
  1. CREATE FUNCTION [dbo].[Ajax](@url [nvarchar](max), @method [nvarchar](max), @arguments [nvarchar](max))

  2. RETURNS TABLE (

  3. [url] [nvarchar](500) NULL,

  4. [html] [nvarchar](max) NULL,

  5. [statusCode] [int] NULL

  6. ) WITH EXECUTE AS CALLER

  7. AS

  8. EXTERNAL NAME [clr.ajax].[ajax].[Http]

这里,external name 之后的三个数据分别是[clr类库项目名].[clr类名].[方法名]

如图所示,我创建的clr项目名是clr.ajax,所以生成的dll是clr.ajax.dll,引用的方法就是[clr.ajax].[ajax].[Http]

第四步:设置数据库权限,允许进行外部访问


 
  1. -- 设置clr enabled允许调用clr程序

  2. sp_configure 'clr enabled',1

  3. go

  4. reconfigure

  5. go

  6. -- 设置数据库允许方位外部

  7. alter database [dbname] set trustworthy on

  8. go

  9. -- 修改程序集的设置,将权限集设置为外部访问

  10. -- 通过sqlserver management studio的界面修改

这里的dbname就是你之前导入程序集的数据库了

第五步:使用自定义函数访问外部链接

自定义函数有三个参数,第一个参数是url,第二个是method,也就是谓词,比如get、post,第三个是参数集,上图已有示例了

如果使用过程中报错,请参考SQL Server 2005 CLR 调用Web Service需要注意的几个问题

----------------------------------

Hmm.....写这么个clr,可不是为了让数据库去玩采集,是为了偷懒!

什么时候用数据库去ajax呢?举几个例子:

静态页网站,当数据库更新后,用触发器或队列调用更新静态页的程序

第三方设置,当本地数据库修改设置后,同步到第三方时

token更新等

注意,可千万别再数据库里玩批量采集哦

原文地址:https://www.cnblogs.com/grj001/p/12224004.html