我使用 SQL Server CLR Integration 创建一个 ASSEMBLY。
加载命令:
CREATE ASSEMBLY TcpClr FROM 'G:\TcpClrTest.dll' WITH PERMISSION_SET = UNSAFE
没有 App.Config
dll代码包含:
string ip=ConfigurationManager.AppSettings["connection"].ToString();
App.config 还包含:
<appSettings>
<add key="connection" value="127.0.0.1"/>
</appSettings>
但是当我执行过程时,SQL Server 显示错误 System.NullReferenceException
SQL Server CLR 集成是否支持 App.config 文件?
最佳答案
您需要将 sqlservr.exe.config 文件放在该实例根文件夹的 \Binn 文件夹中。例如:
C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn
如果您使用的是 SQL Server 2008 R2 (SP1) 或更新版本,您应该能够通过以下查询找到确切位置,该查询显示了 sqlservr.exe 的完整路径:
SELECT [filename] FROM sys.dm_server_services WHERE servicename LIKE N'SQL Server (%';
在您的代码中,您需要在顶部添加这一行:
using System.Configuration;
然后这将起作用:
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlString GetConfig(SqlString WhichOne)
{
ConfigurationManager.RefreshSection("connectionStrings");
return ConfigurationManager.ConnectionStrings[WhichOne.Value].ToString();
}
sqlservr.exe.config 文件的内容:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="Stuff" connectionString="Trusted_Connection=true; Enlist=false;" />
<add name="ClrTest" connectionString="boo hoo" />
</connectionStrings>
</configuration>
重要的是要注意,如“使用应用程序配置...”链接中所述,对配置文件所做的更改不会立即可用。 但是,您不需要通过执行该文章中提到的方法之一(即 DBCC FREESYSTEMCACHE
)并重新启动 SQL Server 来强制重新加载).获取当前信息所需要做的就是通过 ConfigurationManager.RefreshSection(string sectionName) 重新加载您正在使用的特定部分。如上例所示。 请参阅下面有关使用和性能的说明。
资源:
- Using System.Configuration.dll in .NET sprocs and UDFs
- Using an Application Configuration (app.config/web.config) File in SQL Server CLR Integration
此外,除非绝对需要,否则不应将程序集创建为 UNSAFE
。如果您只是想与其他机器建立 TCP 连接,那应该只需要 EXTERNAL_ACCESS
。
使用和性能
正如 Joe B 在 comment below 中所建议的那样,RefreshSection
操作对性能有轻微影响。如果包含刷新的代码每隔几分钟被调用一次以上,那么它可能会产生明显的影响(考虑到配置文件更改的频率较低,这种影响是不必要的)。在这种情况下,您需要从频繁调用的代码中删除对 RefreshSection
的调用,并独立处理刷新。
一种方法是让 SQLCLR 存储过程或标量函数只执行刷新而不执行其他操作。只要对配置文件进行了更改,就可以执行此操作。
另一种方法是卸载 App Domain,这将在下次引用该数据库中的任何 SQLCLR 对象时重新加载配置文件。一种相当简单的方法来重新加载特定数据库中的所有应用程序域(但不是跨整个实例)是翻转 TRUSTWORTHY
设置打开然后再次关闭,或者关闭然后再次打开,具体取决于该设置的当前状态。下面的代码将检查该设置的当前状态并相应地翻转它:
IF (EXISTS(
SELECT sd.*
FROM sys.databases sd
WHERE sd.[name] = DB_NAME() -- or N'name'
AND sd.[is_trustworthy_on] = 0
))
BEGIN
PRINT 'Enabling then disabling TRUSTWORTHY...';
ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
END;
ELSE
BEGIN
PRINT 'Disabling then enabling TRUSTWORTHY...';
ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
END;
请不要使用任何更激烈的方法 -- DBCC FREESYSTEMCACHE
,禁用然后启用 clr enabled
系统设置,重新启动实例等——因为几乎从来没有必要这样做。尤其是重新启动实例,或者 DBCC FREESYSTEMCACHE
会丢弃整个实例的所有缓存数据,这不仅仅影响 SQLCLR。
有关 Linux 上 SQL Server 的更新
从 2017 版开始,SQL Server 现在可在 Linux 上使用(太棒了!)。但是,从应用程序配置文件中读取似乎在 Linux 上不有效。我已经尝试了 sqlservr.exe.[Cc]onfig
和 sqlservr.[Cc]onfig
等的许多组合,但没有任何效果。无法指定配置文件,因为这需要 EXTERNAL_ACCESS
权限,并且在 Linux 上只允许使用 SAFE
程序集(至少目前是这样)。如果我找到让它工作的方法,我会在此处发布详细信息。
关于c# - SQL Server CLR 集成是否支持配置文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28183917/