SQL 服务器 CLR 集成是否支持配置文件?
Does SQL Server CLR Integration support configuration files?
我使用 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 服务器显示错误 System.NullReferenceException
SQL 服务器 CLR 集成是否支持 App.config 文件?
您显然会得到一个 NullReferenceException
,因为 ConfigurationManager.AppSettings["connection"]
是 returning null 然后您在一个 null 上调用 ToString()。
在您发布问题之前,CLR Integration app.config
上 Google 搜索排名最高的页面是这个
在 SQL Server CLR Integration.
中使用应用程序配置 (app.config/web.config) 文件
在 Jonathan Kehayias 的相关文章中,他说
A common part of programming in .NET is to use an configuration file
to store configuration information in an easily modifiable location.
The app.config or web.config file is an invaluable inclusion in most
.NET projects and developers may need to maintain this functionality
as a part of logic sharing between objects in the database and the
application as well. The problem is that SQL CLR doesn't allow use of
the System.Configuration class in SQLCLR projects.
然后他继续详细介绍了一种变通方法,其中涉及编辑项目文件以将新密钥注入将您的 app.config 链接到项目的 ItemGroup。从那里,您可以在代码中进行一些基本的争论,以创建一个 UserDefinedFunction 到 return 您需要的连接字符串或 appSetting。
你最好阅读他在上述 Url 上发表的文章,因为这不是我的领域,我最终会公然抄袭他的内容以提供逐步的操作方法。
您需要将 sqlservr.exe.config 文件放入实例根文件夹的 \Binn 文件夹中。例如:
C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn
如果您使用的是 SQL Server 2008 R2 (SP1) 或更新版本,您应该能够通过以下查询找到确切位置,该查询显示 [= 的完整路径101=]:
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>
请务必注意,如 "Using an Application Configuration..." link 中所述,对配置文件所做的更改不会立即可用。 然而,您不需要通过执行该文章中提到的方法之一(即DBCC FREESYSTEMCACHE
并重新启动来强制重新加载SQL 服务器)。如上例所示,获取当前信息所需要做的就是通过 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 在 中所建议的那样,RefreshSection
操作对性能有轻微影响。如果包含刷新的代码每隔几分钟被调用一次以上,那么它可能会产生明显的影响(考虑到配置文件更改的频率较低,这种影响是不必要的)。在这种情况下,您需要从频繁调用的代码中删除对 RefreshSection
的调用并独立处理刷新。
一种方法是让 SQLCLR 存储过程或标量函数只执行刷新而不执行其他操作。只要对配置文件进行了更改,就可以执行此操作。
另一种方法是卸载 App 域,这将在下次引用该数据库中的任何 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
会丢弃整个实例的 all 缓存数据,这影响的不仅仅是 SQLCLR。
有关 SQL 服务器的更新 LINUX
SQL 服务器现已推出,从 2017 版开始,可在 Linux 上使用(哇哦!)。但是,从应用程序配置文件中读取似乎 不 在 Linux 上工作。我已经尝试了 sqlservr.exe.[Cc]onfig
和 sqlservr.[Cc]onfig
等的许多组合,但没有任何效果。指定配置文件无法工作,因为这需要 EXTERNAL_ACCESS
权限,并且 Linux 上只允许 SAFE
程序集(至少现在是这样)。如果我找到让它工作的方法,我会 post 详细信息在这里。
您是否正在尝试访问与 CLR 运行 相同的 SQL 服务器?如果是这样,您可以使用一种特殊类型的连接字符串,称为 "context connection".
https://msdn.microsoft.com/en-us/library/ms131053.aspx
using(SqlConnection connection = new SqlConnection("context connection=true"))
{
connection.Open();
// Use the connection
}
基本上,您告诉代码它应该使用底层 SQL 服务器(在该上下文中),您甚至不需要指定连接信息。如果您试图 运行 任意可重用代码作为 CLR,您可能犯下了某种软件犯罪行为,不应该这样做。
我就是这样做的。它对我来说工作得很好,我现在可以在任何实例上安装我的程序集,它会工作得很好。
SqlConnectionStringBuilder sqlb = new SqlConnectionStringBuilder("");
sqlb.ContextConnection = true;
string newConnStr = sqlb.ToString();
using (SqlConnection c = new SqlConnection(newConnStr))
{
c.Open();
//This is the database name
DatabaseName = c.Database;
//We need to use some simple SQL to get the server and instance name.
//Returned in the format of SERVERNAME\INSTANCENAME
SqlCommand cmd = new SqlCommand("SELECT @@SERVERNAME [Server]", c);
SqlDataReader rdr = cmd.ExecuteReader();
if (rdr.Read())
{
ServerName = rdr["Server"].ToString();
}
}
我使用 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 服务器显示错误 System.NullReferenceException
SQL 服务器 CLR 集成是否支持 App.config 文件?
您显然会得到一个 NullReferenceException
,因为 ConfigurationManager.AppSettings["connection"]
是 returning null 然后您在一个 null 上调用 ToString()。
在您发布问题之前,CLR Integration app.config
上 Google 搜索排名最高的页面是这个
在 SQL Server CLR Integration.
在 Jonathan Kehayias 的相关文章中,他说
A common part of programming in .NET is to use an configuration file to store configuration information in an easily modifiable location. The app.config or web.config file is an invaluable inclusion in most .NET projects and developers may need to maintain this functionality as a part of logic sharing between objects in the database and the application as well. The problem is that SQL CLR doesn't allow use of the System.Configuration class in SQLCLR projects.
然后他继续详细介绍了一种变通方法,其中涉及编辑项目文件以将新密钥注入将您的 app.config 链接到项目的 ItemGroup。从那里,您可以在代码中进行一些基本的争论,以创建一个 UserDefinedFunction 到 return 您需要的连接字符串或 appSetting。
你最好阅读他在上述 Url 上发表的文章,因为这不是我的领域,我最终会公然抄袭他的内容以提供逐步的操作方法。
您需要将 sqlservr.exe.config 文件放入实例根文件夹的 \Binn 文件夹中。例如:
C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn
如果您使用的是 SQL Server 2008 R2 (SP1) 或更新版本,您应该能够通过以下查询找到确切位置,该查询显示 [= 的完整路径101=]:
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>
请务必注意,如 "Using an Application Configuration..." link 中所述,对配置文件所做的更改不会立即可用。 然而,您不需要通过执行该文章中提到的方法之一(即DBCC FREESYSTEMCACHE
并重新启动来强制重新加载SQL 服务器)。如上例所示,获取当前信息所需要做的就是通过 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 在 RefreshSection
操作对性能有轻微影响。如果包含刷新的代码每隔几分钟被调用一次以上,那么它可能会产生明显的影响(考虑到配置文件更改的频率较低,这种影响是不必要的)。在这种情况下,您需要从频繁调用的代码中删除对 RefreshSection
的调用并独立处理刷新。
一种方法是让 SQLCLR 存储过程或标量函数只执行刷新而不执行其他操作。只要对配置文件进行了更改,就可以执行此操作。
另一种方法是卸载 App 域,这将在下次引用该数据库中的任何 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
会丢弃整个实例的 all 缓存数据,这影响的不仅仅是 SQLCLR。
有关 SQL 服务器的更新 LINUX
SQL 服务器现已推出,从 2017 版开始,可在 Linux 上使用(哇哦!)。但是,从应用程序配置文件中读取似乎 不 在 Linux 上工作。我已经尝试了 sqlservr.exe.[Cc]onfig
和 sqlservr.[Cc]onfig
等的许多组合,但没有任何效果。指定配置文件无法工作,因为这需要 EXTERNAL_ACCESS
权限,并且 Linux 上只允许 SAFE
程序集(至少现在是这样)。如果我找到让它工作的方法,我会 post 详细信息在这里。
您是否正在尝试访问与 CLR 运行 相同的 SQL 服务器?如果是这样,您可以使用一种特殊类型的连接字符串,称为 "context connection".
https://msdn.microsoft.com/en-us/library/ms131053.aspx
using(SqlConnection connection = new SqlConnection("context connection=true"))
{
connection.Open();
// Use the connection
}
基本上,您告诉代码它应该使用底层 SQL 服务器(在该上下文中),您甚至不需要指定连接信息。如果您试图 运行 任意可重用代码作为 CLR,您可能犯下了某种软件犯罪行为,不应该这样做。
我就是这样做的。它对我来说工作得很好,我现在可以在任何实例上安装我的程序集,它会工作得很好。
SqlConnectionStringBuilder sqlb = new SqlConnectionStringBuilder("");
sqlb.ContextConnection = true;
string newConnStr = sqlb.ToString();
using (SqlConnection c = new SqlConnection(newConnStr))
{
c.Open();
//This is the database name
DatabaseName = c.Database;
//We need to use some simple SQL to get the server and instance name.
//Returned in the format of SERVERNAME\INSTANCENAME
SqlCommand cmd = new SqlCommand("SELECT @@SERVERNAME [Server]", c);
SqlDataReader rdr = cmd.ExecuteReader();
if (rdr.Read())
{
ServerName = rdr["Server"].ToString();
}
}