sqlsql-serverstored-proceduresclrclrstoredprocedure

SQL Server CLR Library Stored Procedure static object instantiated more than once


To keep things simple, here is an example of what I am trying to do:

My CLR Library written in C# (it is thread-safe even though I don't show it in the example):

public static class MySP {

    private static Session _session;

    [Microsoft.SqlServer.Server.SqlProcedure]
    [SqlFunction]
    public static void Send(string destination, string message)
    {
        if(_session == null)
            _session = new Session();

        _session.SendMessage(destination, message);
    }

}

Once compiled, I import it into my SQL Server (using Microsoft SQL Server Management Studio):

CREATE ASSEMBLY [MyDLL] FROM 'C:\MyDLL.dll' WITH PERMISSION_SET = UNSAFE;
GO

I import the Stored Procedure:

CREATE PROCEDURE sp_Send (@DestinationName nvarchar(256), @MessageString nvarchar(max))
AS EXTERNAL NAME MyDLL.[NS.MySP].Send
GO

Finally, I have a SQL script that calls the Stored Procedure:

EXEC sp_Send "MyDestination","MyMessage"
GO

Now the problem: Every time I call the Stored Procedure (as shown just above), a new Session object is created (I know, because I see multiple TCP connections open on the other side).

How do I stop the SQL Server from loading my library multiple so that it actually enforces the "static" object paradigm? I only want I single "Session" to be created, until the process of the SQL Server dies, not one static object every time the Stored Procedure is called.

Thank you.

More details (not sure if they were necessary): My "Session" object is loaded from another library (so I technically load 2 DLLs, but only showed one in my example above to keep things simple) which in turns wraps (and loads) a native DLL, not sure if this information was relevant but figured I would add it.

Edit: I would also like to add that if I call my Stored Procedure multiple times in the same SQL script, a single Session object is created. Every time I call that script with multiple Stored Procedure calls, a new Session object is created.


Solution

  • I never programmed a .NET stored procedure, but clearly this happens because the SQL server creates multiple AppDomains (or loads an AppDomain and unloads it after the procedure is done executing). You should be able to see AppDomain activity in the SQL sever log.

    From the little I've googled, the SQL server should only load one AppDomain per database. It could be that the code you wrote somehow throws an unhandled exception, which causes the AppDomain to unload (and the server reloads it when the procedure is called again).

    It is also possible that the SQL server is under memory pressure, in which case it will unload the AppDomain to save memory.

    I don't think you can guarantee just a single Session object within the SQL server, but you can probably minimize the amount of times a new session is created. If you want full control over the session's lifetime, you'll have to host it yourself (perhaps inside a Windows service exposing the session via WCF, and have the SQL server connect to the service in order to interact with the session). As long as SQL server is the host - your session lives by its rules...

    (Then again, it could just be that the info I've read is wrong, and SQL server's AppDomain management is done differently)