从 SQL CLR 调用 Web 服务?

Call web service from SQL CLR?

我有一个 SQL Server 2012 存储过程 return 是 table。我必须修改该 SP 以向 returned table 添加附加值。不幸的是,该附加值来自对网络服务的调用。根据我的研究,我收集到执行此操作的主要方法是使用 SQL 中的 OLE 自动化过程 (sp_OA...) 或 SQLCLR 存储过程。给定 sp_OA... 过程 运行 所在的安全上下文,单个 return 值是一个 VARCHAR(10) 注册密钥,对服务的调用很少(十到二十次)每小时),我猜 SQLCLR 方法是可行的方法。此外,网络服务托管在我们的内部网上,外界无法访问。

有没有更好的方法来完成我需要的?更好意味着更高的性能、更好的安全性、更容易编码和维护

你绝对可以call a WCF service using SQL CLR.

如果您不想这样,您可以用 C# 编写 Windows 服务 watches or polls the table for changes. Depending on how you implement this service, the reaction to a new record would be near immediate. Read also How to notify a windows service(c#) of a DB Table Change(sql 2005)?

然后您可以从 C# 执行服务调用,执行所需的工作并将结果存储在列中。

当你需要更多的信息时,例如在交换过程中获得的额外变量,你可以引入一个新的table来存储它,以及你感兴趣的实际结果。然后加入那个table 来自您问题中的 table。

请不要使用 sp_OA* OLE 自动化程序。它们似乎没有被正式弃用,但 SQLCLR 取代了 OLE 自动化过程和扩展存储过程。

是的,这在 SQLCLR 中很容易完成。您可以找到有关使用 WCF 的示例(如@CodeCaster 的回答所示)或使用 HttpWebRequest / HttpWebResponse(我在此回答中有更多信息:How to invoke webservice from SQL Server stored procedure ). Also, please be aware that sometimes you will need to also add the Serialization Assembly: Using Webservices and Xml Serialization in CLR Integration

编码和维护
Web 服务提供了一个很好的 API,但是如果您更改结构,您将不得不重新编译和重新部署至少其中的一部分。假设交换的信息足够简单,我倾向于认为将其视为标准 Web 请求会增加很多灵活性。您可以创建一个通用的 Web 请求函数(标量或 TVF),它接受参数和 URI 并构造格式正确的 XML 请求并将其发送到 URI。然后它得到响应,只是 returns XML。所以你转移了一点责任,因为你现在需要解析 XML 响应而不是获得一个好的对象。但是,XML 在 SQL 服务器中很容易解析,您可以在任意数量的地方重复使用此功能。而且,如果远程服务曾经更新过,更新存储过程以更改传递给 Web 服务的查询字符串 and/or 更改 XML 响应的解析很简单 ALTER PROCEDURE并且应该很容易测试。无需重新编译/重新部署 SQLCLR 程序集。

安全
无论您想要如何 "pure" 调用 Web 服务,从安全角度来看,最主要的事情是 不要 偷懒并转向 TRUSTWORTHY ON(也显示在来自@CodeCaster 答案的链接页面,不幸的是,互联网上的大多数其他示例)。确保此安全的正确方法是执行以下操作:

  • 签署您的程序集
  • [master] 数据库中,从程序集的 DLL 创建一个非对称密钥。
  • 此外,在 [master] 中,从该非对称密钥创建一个登录名
  • 授予您的新登录 EXTERNAL ACCESS ASSEMBLY 权限
  • 使用 EXTERNAL_ACCESSPERMISSION_SET 创建您的程序集,不是 UNSAFE

更多详情: