gil*_*hal 3 sql-server t-sql azure-sql-database sql-clr
我知道 CLR 存储过程在过程代码中更有效,而 T-SQL 更适合查询 - 但是我很难决定使用什么来满足我的特定需求,我想知道是否还有其他事情我在做决定时应该考虑一下。
我计划创建的代码涉及查询一组数据、实现一些算法(随着时间的推移会变得更加复杂)以及将数据插入到数据库中。此存储过程将由调度程序部署 - 最有可能是 azure webJobs,因为据我所知 Azure SQL 不支持 db 作业。
为什么我想到使用 C#
假设我可以从我的服务器加载 DAL 库,并利用 OOP - 我想我可以为这个问题实现一个对编码器更友好的解决方案 - 至于性能,我认为它会更好或至少在比较中不明显。
为什么我想到使用 T-SQL
我实际上并不认为这是一个更好的解决方案,但可能有一些我忽略的东西可能是 T-SQL 的一个很好的例子,因为对我来说它没有任何意义。
最重要的是
有没有办法可以创建一个 T-SQL 存储过程,调用一个带有复杂对象作为参数的 C# 存储过程 - 执行我的算法并返回要插入的数据,然后从 T-SQL 插入它?似乎是最优雅、性能最好的 (?) 解决方案(假设它是可能的,并且从 T-SQL 调用 CLR 没有任何缺点)。
Sol*_*zky 14
首先,要明确:SQLCLR / .NET / C# / VB.NET 无法查询数据库。只有 T-SQL 可以查询 SQL Server。因此,为了让 SQLCLR 代码以任何方式获取数据或与 SQL Server 交互,它必须SqlConnection
像任何其他 .NET 应用程序一样建立一个.NET 应用程序,并提交 T-SQL,或执行存储过程。
是的,您可以从 T-SQL 调用 SQLCLR(无论是 C# 还是 VB.NET 都无所谓)存储过程、标量函数或表值函数 (TVF) 等。事实上,这是调用 SQLCLR 对象的唯一方法。在程序集中定义的表示 SQLCLR 对象的类需要定义指向这些类的 T-SQL 包装对象,以便可以调用它们。
可以将复杂对象发送到 SQLCLR 对象中,但遗憾的是不能通过表值参数 (TVP) 来完成。但是,您可以在 T-SQL 中创建一个本地临时表,填充它,并在 SQLCLR 对象中从中选择,或者您可以将复杂数据打包到 XML 中并将其作为参数传递给 SQLCLR 对象,该对象将通过XmlReader
.
为了有效地取回数据,您可以:
INSERT
从 SQLCLR 存储过程发出语句INSERT INTO ... EXEC
SQLCLR 存储过程或INSERT INTO ... SELECT
SQLCLR TVF。就加载您的 DAL 库而言,这可以工作,但也可能会出现复杂情况。这完全取决于您的库正在做什么以及正在引用哪些框架库。SQL Server 的 CLR 主机仅支持一小部分 .NET Framework 库,因此如果您的库引用了其他未被“批准”的库,则您将需要手动加载这些库及其任何依赖库(如果有的话)。这里的复杂因素是加载不受支持的 .NET Framework 库需要将它们设置为UNSAFE
,这反过来又需要将数据库设置为TRUSTWORTHY ON
. 另一个复杂问题是,加载 .NET Framework 库一开始甚至可能不可能,因为 SQL Server 内部的 CLR 主机只允许纯 MSIL 程序集,因此您无法加载混合模式程序集。某些 .NET Framework 库当前是混合模式并且不会加载。其他人目前是“纯”的并且会加载,但不能保证在未来的 .NET Framework 更新中这些不会被更改为混合模式程序集。如果/当发生这种情况(并且已经发生,例如System.ServiceModel),那么您将需要重新编码您的程序集。因此,最好坚持使用受支持的框架库,因为这些库可以保证在未来的升级中继续工作。
请记住,应用程序域是每个数据库、每个所有者(程序集的)。这意味着,对于任何特定的 SQLCLR 对象,所有会话/SPID 都将调用相同的代码并共享相同的内存。这就是为什么需要将方法声明为static
. 这就是为什么尝试使用非readonly
静态类变量需要将程序集标记为UNSAFE
:因为此类变量的值可以被另一个会话/SPID 覆盖(例如:SQLCLR 程序集在多个查询同时运行时抛出错误) .
关于问题中的这一陈述:
至于性能,我认为相比之下它会更好或至少不明显。
我不会在这里假设任何事情。有很多因素会影响任一方向的性能:
IsDeterministic=true
,那么您将无法获得它能够参与并行计划的好处(这是 T-SQL UDF 无法做到的)。因此:不要假设;测试!
如果您想了解有关使用 SQLCLR 的更多信息,您可能想查看我正在 SQL Server Central 上撰写的关于此主题的系列文章:SQLCLR 的阶梯(需要免费注册才能访问其内容)。有几篇文章和更多文章,以及大量示例来说明各种功能、安全性等。
关于 Azure SQL 数据库:请注意,虽然SAFE
在 2014 年底添加了对 SQLCLR(仅程序集)的支持,但它最近(据说是暂时)被删除了。客户于 2016 年 4 月 8 日收到电子邮件,称该功能将于 2016 年 4 月 15 日删除。我能找到的最正式的通知是reddit 上的这个帖子:
顾客:
Azure SQL 中对 CLR 程序集的支持是否会很快结束?
我问这个是因为我今天早上(据说)收到一封来自 Microsoft 的电子邮件,指出 4 月 15 日(!!!)之后将不再支持此功能。
Jan,Azure SQL DB 团队中负责性能和弹性池的 PM:
您收到的电子邮件确实是真实的。正如邮件中所述,我们确定 SQL 数据库中用户定义的 SQL CLR 存在安全风险。迄今为止,还没有已知的漏洞利用。为了帮助保护客户的安全,我们已主动暂停在 Azure SQL 数据库中使用用户定义的 SQL CLR。这意味着用户定义的 SQL CLR 将不再起作用。我们将在六个月内向您更新恢复 SQL CLR 的时间表。
和 Tommy,Azure SQL DB 安全团队的 PM:
此问题仅适用于 Azure SQL 数据库服务,不适用于本地 SQL Server 或 IaaS。
归档时间: |
|
查看次数: |
2559 次 |
最近记录: |