One thing that’s somewhat painful about testing/debugging SqlClr application code is managing the connection strings used for internal DB calls inside the system. SqlClr has the notion of a “context connection” connection string which uses the same connection and execution context as that under which the SqlClr code is executing. We use this a lot inside the Aggregation system my team developed.
It can make testing difficult, as when you’re unit testing functionality that uses the context connection and you’re hosted not within SqlServer but within a testing framework these internal calls fail with a “context connection is only available when hosted by SqlServer” error.
I’ve come up with an idiom for managing this in my unit tests. Maybe useful to others as well, so here it is.
I have a utility class with a static constructor which figures out if we’re hosted by SqlServer by inspecting the SqlContext.IsAvailable property and sets a connection string property appropriately. If we’re not hosted by SqlServer the utility class checks the ConfigurationManager for settings stored in AppSettings in our app.config file and uses those.
Here’s the relevant code:
#region Constructors/// <summary>/// Sets up the internal connection string used by the system. /// </summary>static Utility(){ if (SqlContext.IsAvailable) { internalConnectionString = "context connection=true"; } else { try { SqlConnectionStringBuilder sqlSb = new SqlConnectionStringBuilder();
#if DEBUG sqlSb.Pooling = false; #endif sqlSb.DataSource = ConfigurationManager.AppSettings["DBServer"]; sqlSb.InitialCatalog = ConfigurationManager.AppSettings["Database"]; sqlSb.IntegratedSecurity = true; internalConnectionString = sqlSb.ToString(); } catch (Exception e) { // log internalConnectionString = "context connection=true"; } }}
#endregion
#region Properties
/// <summary>/// Connection String used for DB calls within the system. /// If hosted by SqlServer this will be a context connection, /// otherwise we assume this is a test run and use a trusted connection/// string with database and server as configured in app.config. /// </summary>
public static string InternalConnectionString{ get { return internalConnectionString; }}
Then in the SqlClr code we get the connection string like so:
using (SqlConnection conn = new SqlConnection(Utility.InternalConnectionString));
Now our unit tests can operate outside of the SqlServer context. This isn't always appropriate or neccessary, but for our project it's both.
Some caveats/weirdness:
<ItemGroup> . . . <Reference Include="System.Configuration" /> </ItemGroup>