[.NET] 使用C#开发SQL Function来提供数据 - 天气预报

范例下载

范例程序代码:点此下载

问题情景

开发人员在设计一些数据汇整的系统服务时,可能会选择WCF、WebAPI、SignalR...等等通讯框架,来开放API给客户端开发人员使用。但在一些特殊的开发案例中,客户会很婉转的告知开发人员,上述这些技术太新,客户端开发人员无法理解与使用这样的技术。

为了满足这类客户的需求,开发人员可以选择将系统服务封装成为SQL Function并且布署到SQL数据库;后续客户端开发人员透过SELECT语法来查询SQL数据库,就可以取得系统服务所提供的数据,大幅降低客户端开发人员使用系统服务的技术门坎。

本篇文章介绍如何将系统服务封装成为SQL Function来提供数据,为自己留个纪录也希望能帮助到有需要的开发人员。

数据源

为了降低范例的复杂度,后续范例使用CLK.OpenDataAPIs套件中的WeatherAPI类别做为系统服务,来示范如何将系统服务封装成为SQL Function。

这个CLK.OpenDataAPIs套件可以由NuGet取得,套件中的WeatherAPI类别透过HTTP通讯协议从政府数据开发平台(http://data.gov.tw/)取得县市天气预报,用来提供天气预报的相关数据给开发人员使用。

功能开发

01.建立DataBase

示范如何将系统服务封装成为SQL Function,第一个步骤就是建立一个用来安装SQL Function的范例数据库:ClrSampleDB。

02.设定DataBase - 开启SQLCLR

接着为了在SQL Server中执行C#所开发的SQL Function,必须要先透过下列的SQL指令,在SQL Server中开启CLR的功能。

EXEC sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

03.建立数据库项目

完成了上列数据库的基本设定,就可以开启Visual Studio来动手建立数据库类型项目:CLK.OpenDataAPIs.SqlExtension。

04.参考CLK.OpenDataAPIs

接着为CLK.OpenDataAPIs.SqlExtension项目,加入CLK.OpenDataAPIs套件来做为系统服务。这个CLK.OpenDataAPIs套件可以由NuGet取得,但是在Visual Studio中数据库类型项目,并不支持使用NuGet来加入套件参考,所以开发人员在这个步骤要手动加入套件参考。

  • 开启NuGet Package Explorer来下载CLK.OpenDataAPIs的DLL:CLK.OpenDataAPIs.dll。

  • 取得CLK.OpenDataAPIs.dll之后,就可以将这个套件DLL加入CLK.OpenDataAPIs.SqlExtension数据库项目的参考。

05.设定CLK.OpenDataAPIs

接着还需要将CLK.OpenDataAPIs.dll的属性变更为下图的内容,其中最重要的就是「权限集合」这个属性必须要设定为「外部」,这样SQL Server在执行的时候,才会允许CLK.OpenDataAPIs.dll开启HTTP通讯协议来取得资料。

06.设定数据库项目 - 可信任 & 权限等级

设定完加入的套件参考之后,还要接着设定数据库项目的属性:可信任、权限等级,这两个属性必须要设定为下图所示的内容,后续SQL Server在执行的时候,才会允许这个数据库项目CLK.OpenDataAPIs.SqlExtension.dll,使用CLK.OpenDataAPIs.dll开启HTTP通讯协议来取得资料。

07.封装SQL Function

完成上述这个琐碎的设定之后,就可以写程序来将CLK.OpenDataAPIs套件中的WeatherAPI类别封装成为SQL Function。

public partial class UserDefinedFunctions
{
[SqlFunction(TableDefinition = @"LocationName nvarchar(MAX),
IssueTime datetime,
StartTime datetime,
EndTime datetime,
MaxTemperature int,
MaxTemperatureUnits nvarchar(MAX),
MinTemperature int,
MinTemperatureUnits nvarchar(MAX),
ProbabilityOfPrecipitation int,
ProbabilityOfPrecipitationUnits nvarchar(MAX),
Weather int,
WeatherText nvarchar(MAX),
ComfortIndexText nvarchar(MAX)",
FillRowMethodName = "WeatherAPI_GetAllForecast_FillRowMethod")]
public static IEnumerable WeatherAPI_GetAllForecast()
{
return new WeatherAPI().GetAllForecast();
}
} public partial class UserDefinedFunctions
{
// Methods
public static void WeatherAPI_GetAllForecast_FillRowMethod(object row,
ref SqlString LocationName,
ref SqlDateTime IssueTime,
ref SqlDateTime StartTime,
ref SqlDateTime EndTime,
ref SqlInt32 MaxTemperature,
ref SqlString MaxTemperatureUnits,
ref SqlInt32 MinTemperature,
ref SqlString MinTemperatureUnits,
ref SqlInt32 ProbabilityOfPrecipitation,
ref SqlString ProbabilityOfPrecipitationUnits,
ref SqlInt32 Weather,
ref SqlString WeatherText,
ref SqlString ComfortIndexText)
{
// Require
Forecast forecast = row as Forecast;
if (forecast == null) throw new InvalidOperationException(); // Fill
LocationName = forecast.LocationName;
IssueTime = forecast.IssueTime;
StartTime = forecast.StartTime;
EndTime = forecast.EndTime;
MaxTemperature = forecast.MaxTemperature;
MaxTemperatureUnits = forecast.MaxTemperatureUnits;
MinTemperature = forecast.MinTemperature;
MinTemperatureUnits = forecast.MinTemperatureUnits;
ProbabilityOfPrecipitation = forecast.ProbabilityOfPrecipitation;
ProbabilityOfPrecipitationUnits = forecast.ProbabilityOfPrecipitationUnits;
Weather = forecast.Weather;
WeatherText = forecast.WeatherText;
ComfortIndexText = forecast.ComfortIndexText;
}
}

这段封装的步骤有点复杂,拆成几块会比较好理解。

首先在Function中将回传数据格式定义为IEnumerable,这代表Function会回传一个数据集合。

在SQL Server中是以Table来处理数据,没有办法处理IEnumerable类型回传的数据集合。为了将IEnumerable类型转换为Table让SQL Server能够处理,必须要先在SqlFunction特性的TableDefinition属性中,定义IEnumerable类型的数据集合会被转换为何种格式的Table的Schema。

SQL Server没有提供自动依照Table Schema来转换IEnumerable类型数据集合的功能,必须要开发人员写程序将数据集合中的每个数据对象,转换为Table中的每一行Row。而在SqlFunction特性的FillRowMethodName属性中,可以指定用来将数据对象转换为Table Row的转换函式。

在这个将数据对象转换为Table Row的转换函式中,必须依照先前SqlFunction特性的TableDefinition属性所定义的Table Schema,来定义做为函式输出的ref参数,在这其中每个ref参数对应到一个Table Schema的字段。

最后就是将每个数据对象属性,填入对应的ref参数,用来输出成为每个Table Row的字段内容。至此就完成整个SQL Function的设计,这个SQL Function在执行的时候,就会取得数据集合并且依照程序定义将每个数据对象转为Table Row来组成Table提供给SQL Server使用。

08.发行数据库项目

将CLK.OpenDataAPIs套件中的WeatherAPI类别封装成为SQL Function之后,还需要将包含这个SQL Function的数据库项目,发行到先前建立的范例数据库:ClrSampleDB里面。

09.检视DataBase

完成上列一连串的动作之后,就可以在数据库看到数据库项目中发行的组件以及函数。

功能使用

在SQL Server中,C#开发SQL Function与原生的SQL Function是同等级的存在,可以透过SQL语法来调用。

SELECT * FROM WeatherAPI_GetAllForecast()

当然也可以将SQL Function封装成为View,让使用者更方便的使用。

参考数据

张小呆的碎碎念 - 使用 SQLCLR 来实作 SPLIT

[.NET] 使用C#开发SQL Function来提供数据 - 天气预报的更多相关文章

  1. [.NET] 使用C#开发SQL Function来提供服务 - 简讯发送

    [.NET] 使用C#开发SQL Function来提供服务 - 简讯发送 范例下载 范例程序代码:点此下载 问题情景 在「使用C#开发SQL Function来提供数据 - 天气预报」这篇文章中,介 ...

  2. SQL Function 自定义函数

    目录 产生背景(已经有了存储过程,为什么还要使用自定义函数) 发展历史 构成 使用方法 适用范围 注意事项 疑问   内容 产生背景(已经有了存储过程,为什么还要使用自定义函数) 与存储过程的区别(存 ...

  3. 大型系统开发sql优化总结(转)

    Problem Description: 1.每个表的结构及主键索引情况 2.每个表的count(*)记录是多少 3.对于创建索引的列,索引的类型是什么?count(distinct indexcol ...

  4. SQL开发——SQL语法

    文档资料参考: 参考:http://www.w3school.com.cn/sql/sql_syntax.asp 参考:http://wiki.jikexueyuan.com/project/sql/ ...

  5. 后台商品搜索功能开发SQL

    在做后台的商品搜索功能开发时遇到了一些问题记录下来 版本一 <select id="SelectByNameAndParentId resultMap="Base_resul ...

  6. sql:function

    --查询权限函数 --1 declare @names varchar(3000) set @names='' select @names=@names+isnull(AdminPermissForm ...

  7. SQL Function(方法)

    1.为什么有存储过程(procedure)还需要(Function) fun可以再select语句中直接调用,存储过程是不行的. 一般来说,过程显示的业务更为复杂:函数比较有针对性. create f ...

  8. sql function递归

    alter function Fn_GetUserGroupRelation ( @DHsItemID int ) returns nvarchar(1024) begin declare @Col_ ...

  9. asp.net 开发 sql server 转 oracle

    前段时间我们公司项目 要把sql server 转oracle 分享一下心得 也记录一下问题 开始我研究了一段时间 然后下载了 oracle 11g 版本 和 PL/SQL(客户端) 和sql ser ...

随机推荐

  1. CSS基础(二):基础和语法

    CSS语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明.选择器通常是您需要改变样式的 HTML 元素. selector {declaration1; declaration2; . ...

  2. 让Windows 7变成WIFI热点

    360要推便携路由器,个人觉得其主要目的是盯住了用户无线设备上的信息.因为如果用户移动设备都通过它这个路由器走的话,未加密的数据全部在他掌控之中. 其实Windows 7以上的系统是非常容易建立无线热 ...

  3. SetHandleInformation设置内核对象标志

    当父进程创建子进程时,子进程将继承父进程的内核对象.这时如果要控制子进程使用父进程的内核对象.可以使用 SetHandleInformation设置. BOOL SetHandleInformatio ...

  4. 实现让Lync client也能够"潜水"隐身聊天

    看到MSN或QQ,都支持隐身聊天. Lync Server  2013也是支持的.   1.Server端:Lync 2013 Server 缺省策略是没有设置显示脱机功能.(设置前截图)   2.直 ...

  5. char str[]和char *str的区别

    1.http://blog.csdn.net/szchtx/article/details/10396149 char ss[]="C++";  ss[0]='c';        ...

  6. SmartJS 第一期(0.1)发布 - AOP三剑客

    隔了好久才终于又发布了一点东西,SmartJS是最近才开始搞的一个开源js库,目的是做一些比较有特点的事情(smartjs暂时也是依赖于jquery). SmartJS的内容规划比较多,也无法在短时间 ...

  7. [OpenCV] Face Detection

    即将进入涉及大量数学知识的阶段,先读下“别人家”的博文放松一下. 读罢该文,基本能了解面部识别领域的整体状况. 后生可畏. 结尾的Google Facenet中的2亿数据集,仿佛隐约听到:“你们都玩儿 ...

  8. [python]pip常用命令(转载)

    用阿里云服务器,使用pip安装第三方库的时候卡的要死.所以我就想pip能不能安装本地的包. 找到了这篇博客: http://me.iblogc.com/2015/01/01/pip%E5%B8%B8% ...

  9. IE11之F12 Developer Tools--概述篇

    打开Developer Tools的方法: a. 点击F12 b. 在浏览器中选择Tools-->F12 Develooper Tools 打开后图示: 从上图我们可以看到,Developer ...

  10. Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划)

    Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到 ...