Question

I am looking to replace some hard-coded values in CLR code (SQL 2012), I came across the use of config files here - https://stackoverflow.com/questions/16177769/assembly-configuration-clr-stored-procedure. A couple responses said it is better to save key/value pairs in tables as opposed to config files, one reason being that it wasn't supported in SQL 2014+.

Our developer says it works fine in SQL 2014, so I'm not concerned with that, but I do think storing the values in a table on the local database would be a better idea.

  1. Can anyone else confirm that config files are or are not supported in SQL 2014+?
  2. Is there any documentation on best practices for storing key/value pairs in a table, or any reason not to?
Was it helpful?

Solution

I am pretty sure that the sqlservr.exe.config config file works in SQL Server 2014, but will take me a few minutes to confirm. I am also pretty sure that it is not "officially" supported, and so not "recommended" to use, but on occasion I find it handy to use and have done so.

Whether or not the location of the data should be in a config file or table depends largely on what the overall needs are. How often will the values change? You say "hard-coded", but lookup values can change per each release, sometimes. Do you want to have to run an UPDATE statement, or find a way to include maintaining this config file in your build process (you need to find some way to ensure that it is always there).

Also, will the values ever be needed outside of the .NET / SQLCLR code? Having them in a table makes them more available to all existing queries.

Also, will there ever be a need for separation between databases for these values? With a config file it is shared across all App Domains for that Instance. A config table can just as easily be placed in a common Database (assuming multiple databases might want the values) or placed into each Database. You can have separation of values within the config file, but that requires having different names for the keys, and that makes it harder to standardize within the .NET code.

If it makes sense enough to be read-only and common / shared, then why not start out trying the config file approach, and if you find any reason that it doesn't meet your needs, just move it over to being stored in a table. After all, neither option is going to require that many hours of work, and the time difference between them is negligible, so it won't cost much if you do need to switch to the other approach.

NOTES:

  1. In the StackOverflow question linked in this question, the answer from @David states that this config file is no longer working as of SQL Server 2014. I have just tested and confirmed that it does indeed work on SQL Server 2014 and even on 2016!

  2. In the StackOverflow question linked in this question, the answer from @Remus states that storing in the DB is preferred due to the config file being disconnected from SQL Server and possibly not on related servers, or possibly out-of-synch with them. This point should not be ignored, and those concerns should help the team look at the big picture of how the application lives and hence come to a more informed decision. However, there are certainly scenarios that do not have such concerns and which allow for the build process to ensure that this config file is in place in each environment, just as that build process does the same checks for config files on web servers, etc.

  3. In the blog referenced in @Remus's answer in the linked question, the author mentions an "issue" with getting errors attempting to read AppSettings, and a work-around is noted to call ConfigurationManager.ConnectionStrings.Count;. That is correct. However, you don't need to make that call each time; it only needs to be done once for the life of the App Domain. So, it works just fine to place it in a static class constructor as follows:

    static _your_class_name_here_()
    {
        int _BugBeGone = ConfigurationManager.ConnectionStrings.Count;
    }
    

    And no, you do not need to have a <connectionStrings> section in your config file for the above to work.

  4. That same blog post also mentions that the config file is read only once, when the App Domain is created and that you will need to restart the instance -- or possibly unload the App Domain -- in order to have any changes made to the config file after the App Domain is created become visible to your code. The first part is correct: the config file is loaded once and cached for the life of the App Domain. However, you do not need to restart the Instance in order to refresh the config values, nor even unload the app domain. You just need to call:

    ConfigurationManager.RefreshSection("appSettings");
    

    But don't do that for every call, unless the function or stored procedure is meant to run occasionally. If this is something that will run at least once per second, or more often, then create a separate function or stored procedure to do just that refresh and execute it when necessary.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top