简体   繁体   English

SQL Server CLR库存储过程静态对象被多次实例化

[英]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): 我的CLR库是用C#编写的(即使在示例中未显示,它也是线程安全的):

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): 编译后,我将其导入我的SQL Server(使用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: 最后,我有一个调用存储过程的SQL脚本:

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). 现在的问题是:每次我调用存储过程(如上所示)时,都会创建一个新的Session对象(我​​知道,因为我看到另一侧打开了多个TCP连接)。

How do I stop the SQL Server from loading my library multiple so that it actually enforces the "static" object paradigm? 如何阻止SQL Server多次加载我的库,以便它实际上强制执行“静态”对象范例? 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. 我只希望创建一个“会话”,直到SQL Server进程终止,而不是每次调用存储过程时都不要创建一个静态对象。

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. 更多详细信息(不确定是否有必要):我的“会话”对象是从另一个库加载的(因此我从技术上加载了2个DLL,但在上面的示例中仅显示了一个DLL以使事情简单),这又包装(并加载了)本机DLL,不确定此信息是否相关,但认为我会添加它。

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. 编辑:我还要补充一点,如果我在同一SQL脚本中多次调用存储过程,则会创建一个Session对象。 Every time I call that script with multiple Stored Procedure calls, a new Session object is created. 每次我使用多个存储过程调用该脚本时,都会创建一个新的Session对象。

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). 我从未编写过.NET存储过程,但是很明显,这是因为SQL Server创建了多个AppDomain(或加载了AppDomain,并在过程执行完成后将其卸载了)。 You should be able to see AppDomain activity in the SQL sever log. 您应该能够在SQL服务器日志中看到AppDomain活动。

From the little I've googled, the SQL server should only load one AppDomain per database. 从我搜索过的内容来看,SQL Server每个数据库只应加载一个AppDomain。 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). 您编写的代码可能以某种方式引发了未处理的异常,这导致AppDomain卸载(并且当再次调用该过程时,服务器会重新加载它)。

It is also possible that the SQL server is under memory pressure, in which case it will unload the AppDomain to save memory. SQL Server也有可能承受内存压力,在这种情况下,它将卸载AppDomain以节省内存。

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. 我认为您不能保证SQL Server中只有一个Session对象,但是您可以最大程度地减少创建新会话的次数。 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). 如果要完全控制会话的生存期,则必须自己托管它(也许在Windows服务中,可以通过WCF公开该会话,并让SQL Server连接到该服务以便与会话进行交互)。 As long as SQL server is the host - your session lives by its rules... 只要SQL Server是主机,您的会话就会按照其规则运行...

(Then again, it could just be that the info I've read is wrong, and SQL server's AppDomain management is done differently) (再一次,可能只是我阅读的信息有误,并且SQL Server的AppDomain管理以不同的方式进行)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM