如何在 SQL Server 的 clr 存储过程中执行动态 .net 代码
Posted
技术标签:
【中文标题】如何在 SQL Server 的 clr 存储过程中执行动态 .net 代码【英文标题】:How to execute dynamic .net code in clr stored procedure in SQL Server 【发布时间】:2011-05-20 14:09:14 【问题描述】:有没有办法在 SQL Server 中动态更改 CLR 过程的代码?
假设您有一个在 MS SQL Server 2008 R2 中部署了业务逻辑的程序集。这个程序集(或多个程序集)一直在使用(例如,在多个并发查询中为表的每一行调用一些函数)。所以你不能只是放弃组装。有没有办法动态改变我的业务逻辑或执行外部可变代码?
我已经探索过这些方法,但没有一个奏效:
-
反射.发射
Mono.Cecil
在 SQL Server 中部署的程序集中加载外部程序集
更新: 问题不在于发布过程:我希望能够通过 GUI 动态设置一些安全规则。
例如,一些用户应该只能看到没有地址的客户或去年的交易等等。
规则并不复杂,但几乎每天都在变化,我们不能将它们放入代码中。其余的业务逻辑在 TSQL 中实现。选择 CLR 是因为性能问题(动态 SQL 太慢)。
还有另一种选择:生成集群视图(在 WHERE 部分使用规则),但速度不够快。
更多细节:
假设我们有一些代码选择大表 dbo.Transactions 的一部分
select *
from dbo.Transactions
where ... --filters from your business logic
如果我们想过滤结果以显示允许的行,我们可以生成一些索引视图并将其与结果集连接起来,如下所示:
select *
from dbo.Transactions t
inner join dbo.vw_Transactions v
on t.id = v.id
where ... --filters from your business logic
但是如果我们在大多数情况下检查执行计划,查询分析器会决定不过滤 dbo.Transaction 然后使用 vw_Transactions 连接,而是先连接然后过滤(这绝对不可取)。 FORCE ORDER 之类的提示无济于事。
【问题讨论】:
所以您很乐意绕过任何正式的发布流程?这就是你拥有 CLR 的原因吗? @gbn 问题不在于发布过程:我希望能够通过 GUI 动态设置一些安全规则。例如,一些用户应该只能看到没有地址的客户或去年的交易等等。规则并不复杂,但它们几乎每天都在变化,我们不能将它们放入代码中。其余的业务逻辑在 TSQL 中实现。选择 CLR 是因为性能问题(动态 SQL 太慢)。还有另一种选择:生成集群视图(在 WHERE 部分使用规则),但速度不够快。 这在你的问题中并不明显...... 【参考方案1】:我不是 CLR 汇编专家,但显而易见的选择是:
-
改变组件
在事务中删除并重新创建程序集
定义维护时段并随后进行部署
gbn 关于发布过程的观点很好。如果您的程序(以及您的业务运营)真的每天 24 小时不间断地运行,那么大概您已经拥有某种形式的系统冗余并建立了用于修补和升级应用程序的维护程序?如果是这样,只需在通常的维护窗口中部署新代码即可。
【讨论】:
修改想法后,我发现在极少数情况下需要重新部署,这样我们就可以在没有人连接的情况下执行(应用程序不是 24x7 运行)。 @Pondlife,@gbn 你是对的:问题是关于发布过程(但它被掩盖了)【参考方案2】:有一个很好的动态评估算术表达式库(带参数)-Flee
在我的情况下,我不必执行 任何 .Net 代码 - 只需像“Date > '20100101' Or Status = 2”这样的表达式,所以 Flee 几乎完全满足。唯一的问题是它的逻辑运算符不适用于 SqlBoolean 类型(用于 sql 表达式),但添加此功能并不是什么大问题。
但在一般情况下,似乎不可能在 Sql Server 主机内执行动态 .Net 代码。
【讨论】:
这是不可能的,因为 Reflection.Emit 被主机保护属性阻止了。见msdn.microsoft.com/en-us/library/ms403285.aspx以上是关于如何在 SQL Server 的 clr 存储过程中执行动态 .net 代码的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL Server CLR 程序集中使用 Microsoft Solver Foundation