Is it safe to change static readonly variables in C# SQLCLR?

风流意气都作罢 提交于 2019-12-05 04:52:51

Are static read-only variables in SQLCLR unique for every sql connection/sql query/transactions or do they share data between different SQLCLR procedures calls?

An Assembly residing inside of SQL Server (i.e. SQLCLR) gets loaded into a single App Domain which is shared across all sessions. There can be multiple App Domains since they are specific to each Database and owner (i.e. Authorization) combination. But any one particular SQLCLR object will only reside in one particular Assembly, so all calls to it do share that single instance. This is why all SQLCLR methods need to be static, since they are not per-Session. So yes, static member/class variables are shared, which is why they need to be declared as readonly, else the Assembly needs to have a PERMISSION_SET of UNSAFE if a static class variable is not marked as readonly.

Is it possible to have painless global state, safe from other SQLCLR procedures calls?

No, at least not in any simple, built-in fashion. A static class variable that is a Collection can be thought of as a real table created in tempdb (not the same as a Global Temporary Table -- ##Table). Once the variable is created it will remain and won't disappear once the "session" that created it ends, but it is accessible to all sessions. So if you need to have per-Session separation, then you need to have a property of the static collection be a differentiator -- something to tell each session apart. And you could possibly get the current session_id / @@SPID and use that, as long as you clear out all entries having that same session_id at the beginning of each process since session_id values are re-used by SQL Server. But there is no way to clean up entries for session_id values that are not re-used, unless you do that as a final step at the end of the process (a step that might not be called if the process runs into an exception). So, not impossible, but will take a little but of work and a lot of testing :-).

It should also be understood that this is not specific to SQLCLR Stored Procedures, but affects all methods and objects running in a particular App Domain. Meaning, static class variables are shared with all code that can access the class, which can be SQLCLR Triggers, Functions, and probably also User-Defined Aggregates and User-Defined Types.

PLEASE NOTE, one nuance that you need to be aware of with regards to static variables and how SQL Server manages memory is:

Occasionally SQL Server, if it is running out of physical memory, may decide to unload one or more App Domains. You can see this behavior in the SQL Server error log by searching for "memory pressure" since there will be entries in the form of:

AppDomain X ({database_name}.{owner_name}[runtime].Y) is marked for unload due to memory pressure.

Unloading the App Domain will clear out the static variables. When it gets reloaded upon the next call to the SQLCLR object, the static variables will be created again.

SO, if the static variable is being used to maintain state between calls that is necessary for "proper" operation, then you need to find another way as that data cannot be guaranteed to exist between calls.

If you need per-Session global state, then you need to use SQL Servers built-in mechanisms by executing T-SQL statements using Context Connection = true; as the Connection String. You can use:


For more information on working with SQLCLR in general, please see the series I am writing on this topic on SQL Server Central (free registration is required):

Stairway to SQLCLR

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!