I use SQL Server CLR Integration to create an ASSEMBLY.
Load Command:
CREATE ASSEMBLY TcpClr FROM 'G:\TcpClrTest.dll' WITH PERMISSION_SET = UNSAFE
Without App.Config
The dll code contains :
string ip=ConfigurationManager.AppSettings["connection"].ToString();
Also the App.config contains :
<appSettings>
<add key="connection" value="127.0.0.1"/>
</appSettings>
But when I execute the PROCEDURE,the SQL Server shows an error System.NullReferenceException
Does SQL Server CLR Integration support App.config files?
The CLR Enabled alert indicates that the Common Language Runtime (CLR) configuration option is enabled for the SQL Server instance. You can run managed code in the . NET Framework. Use the Server Configuration view to reconfigure this option on SQL Server 2005 instances.
For SQL Server users and application developers, CLR integration means that you can now write stored procedures, triggers, user-defined types, user-defined functions (scalar and table valued), and user-defined aggregate functions using any . NET Framework language, including Microsoft Visual Basic .
We need to enable CLR because the integration services catalog uses CLR procedures. Integration services catalog has to be created on the server in order to be able to deploy SSIS packages to SQL Server.
You need to place a sqlservr.exe.config file in the \Binn folder of that instance's root folder. For example:
C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn
If you are using SQL Server 2008 R2 (SP1) or newer, you should be able to find the exact location via the following query, which shows the full path to sqlservr.exe:
SELECT [filename] FROM sys.dm_server_services WHERE servicename LIKE N'SQL Server (%';
In your code, you need this line at the top:
using System.Configuration;
And then this will work:
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlString GetConfig(SqlString WhichOne)
{
ConfigurationManager.RefreshSection("connectionStrings");
return ConfigurationManager.ConnectionStrings[WhichOne.Value].ToString();
}
Contents of the sqlservr.exe.config file:
<?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>
It is important to note that, as stated in the "Using an Application Configuration..." link, changes made to the config file are not immediately available. HOWEVER, you do not need to force a reload by doing one of the methods mentioned in that article (i.e. DBCC FREESYSTEMCACHE
, and restarting SQL Server). All that is required to get current information is to reload the particular section you are using via ConfigurationManager.RefreshSection(string sectionName) as shown in the example above. Please see note below regarding usage and performance.
Resources:
Also, unless you absolutely need to, you shouldn't create your assembly as UNSAFE
. If you are just trying to make TCP connections to other machines, that should only require EXTERNAL_ACCESS
.
USAGE AND PERFORMANCE
As suggested by Joe B in a comment below, there is a slight performance hit for the RefreshSection
operation. If the code containing the refresh is going to be called more than once every couple of minutes, then it can have a noticeable impact (an impact that is unnecessary given the lack of frequency of a config file changing). In this case, you will want to remove the call to RefreshSection
from the code that is called frequently and handle the refresh independently.
One approach would be to have a SQLCLR Stored Procedure or Scalar Function that just does the refresh and nothing else. This can be executed whenever a change it made to the config file.
Another approach would be to unload the App Domain which will reload the config file upon the next time any SQLCLR object in that database is referenced. One fairly simple method to reload all App Domains in a particular Database (but not across the entire Instance) is to flip the TRUSTWORTHY
setting On and then Off again, or Off and then On again, depending on the current state of that setting. The code below will check the current state of that setting and flip it accordingly:
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;
Please do not use any of the more drastic methods -- DBCC FREESYSTEMCACHE
, disabling then enabling the clr enabled
system setting, restarting the Instance, etc -- as it is almost never necessary to do so. Especially restarting the Instance, or DBCC FREESYSTEMCACHE
which drops all cached data for the entire Instance, which affects much more than just SQLCLR.
SQL Server is now, starting with version 2017, available on Linux (woo hoo!). However, it seems that reading from the app config file does not work on Linux. I have tried many combinations of sqlservr.exe.[Cc]onfig
and sqlservr.[Cc]onfig
, etc, and the like and have not gotten anything to work. Specifying a config file can't work as that requires EXTERNAL_ACCESS
permission and only SAFE
Assemblies are allowed on Linux (as of right now, at least). If I find a way to get it working I will post the details here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With