有一些博客文章介绍了如何在SQL Server中使用带有SQLCLR的F#,这些帖子非常有用:http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/,http://thelastexpression.blogspot.com/2012/04/f-agents-and-sqlclr.html,https://rojepp.wordpress.com/2011/08/03/f_on_sqlclr/,Can the F# core libs be SQLCLR-approved? 对于C#方法:http://www.sqlservercentral.com/Authors/Articles/Solomon_Rutzky/294002/
我想知道/希望随着时间的推移,有一篇博文在那里,我还没有找到或在这里找到答案,它解决了如何使用F#和SQLCLR这样组装可以使用Visual Studio(或其他一些工具)编写成十六进制文件,就像使用C#部署一样(我无法通过SQL Server Management Studio在服务器上安装代码),并且至少比使用'更安全'值得信赖的'或'不安全'。之前我编写了F#和许多T-SQL,我在Common Lisp中编写的原型(现在必须存在于SQL Server中)将更好地映射到F#(并且让我比使用C#更快乐。)
答案 0 :(得分:3)
我对第一个链接(http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/)中显示的方法持怀疑态度,因为它没有直接显示 FSharp.Core 库的加载,因此不清楚作者不必设置TRUSTWORTHY ON
以至少使该部分正常工作。似乎非常可疑的是,在第5步中,基于非对称密钥的登录被授予了错误的权限:
GRANT EXTERNAL ACCESS ASSEMBLY TO FSHARP_CLR_Login
授予EXTERNAL ACCESS ASSEMBLY
不允许将程序集设置为UNSAFE
。 需要UNSAFE ASSEMBLY
权限。在撰写帖子时可能是一个复制/粘贴错误,但没有显示sys.databases
TRUSTWORTHY
当前OFF
的证据,或者在创建登录并授予其权限之前,作者的代码无效。
所以,我只是通过安装最新版本的FSharp.Core - 4.1.2来尝试这个 - 这就是我发现的:
通过以下方式确认TRUSTWORTHY
为OFF
(即0
):
SELECT [name], is_trustworthy_on FROM sys.databases WHERE [database_id] = DB_ID();
尝试将 FSharp.Core 加载为SAFE
,只是为了查看它是否有效:
USE [TestDB];
CREATE ASSEMBLY [FSharp.Core]
FROM N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll'
WITH PERMISSION_SET = SAFE;
收到以下错误:
Msg 6211,Level 16,State 1,Line 32
CREATE ASSEMBLY失败,因为安全程序集“FSharp.Core”中的类型“Microsoft.FSharp.Collections.FSharpMap`2”具有静态字段“empty”。安全程序集中静态字段的属性必须在Visual C#,Visual Basic中的ReadOnly或Visual C ++和中间语言中的initonly中标记为只读。
尝试再次加载 FSharp.Core ,但是UNSAFE
:
USE [TestDB];
CREATE ASSEMBLY [FSharp.Core]
FROM N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll'
WITH PERMISSION_SET = UNSAFE;
有效。但是,我没有将数据库设置为TRUSTWORTHY ON
,也没有创建登录并授予EXTERNAL ACCESS ASSEMBLY
权限。含义:可能通过运行时验证而不是加载时验证来发现违规。我无法超越这部分进行测试,但我希望会发生错误。
如果关于此程序集的UNSAFE
权限集确实发生错误,那么您可以处理该问题而无需设置TRUSTWORTHY ON
,但您需要在master中创建一个证书,基于证书的登录:
USE [master];
CREATE CERTIFICATE [FSharpCert45]
FROM EXECUTABLE FILE =
N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll';
CREATE LOGIN [FSharpLogin45] FROM CERTIFICATE [FSharpCert45];
GRANT UNSAFE ASSEMBLY TO [FSharpLogin45];
如果您的程序集也需要标记为UNSAFE
,那么您可以从master
中的DLL创建非对称密钥,然后从该非对称密钥创建基于密钥的登录,然后授予基于密钥的登录UNSAFE ASSEMBLY
权限。 (这假定您的程序集已签名 - 并使用密码保护)
当然,以上所有假设您都可以将DLL放到服务器上,或者至少放到SQL Server服务帐户可以访问的共享上,并且您确实提到要通过十六进制字节部署它。这应该是可能的:
True
。这将导致发布过程将DLL包含在构建脚本中。Unsafe
语句,因为发布脚本是增量更改。如果是这种情况,请转到项目属性,然后在项目设置下,选中创建脚本(.sql文件)(如果尚未选中)框。这将导致构建过程始终生成 _Create.sql 脚本,并且肯定会有 FSharp.Core 的CREATE ASSEMBLY
语句。CREATE ASSEMBLY
语句将程序集加载到目标数据库中(即程序集也被加载到其中)。 CREATE ASSEMBLY [FSharp.Core] FROM 0x...
语句 也是<{1}}中创建对象的门票,如下所示:
CREATE ASSEMBLY [FSharp.Core] FROM 0x...
这在SQL Server 2012上对我有用,唯一的区别是我使用的是文件路径而不是十六进制字节。