SQL异常:在此批处理中无法调用"模拟会话安全上下文",因为同时批处理已调用它

kas*_*sey 5 c# asp.net connection-pooling sql-server-2005 sql-server-mars

从我们的Web应用程序打开到SQL Server 2005的连接时,我们偶尔会看到此错误:

无法在此批处理中调用"模拟会话安全上下文",因为同时批处理已调用它.

我们使用MARS和连接池.

该异常源自以下代码:

protected SqlConnection Open()
{
    SqlConnection connection = new SqlConnection();
    connection.ConnectionString = m_ConnectionString;
    if (connection != null)
    {
        try
        {
            connection.Open();
            if (m_ExecuteAsUserName != null)
            {
                string sql = Format("EXECUTE AS LOGIN = {0};", m_ExecuteAsUserName);
                ExecuteCommand(connection, sql);
            }
        }
        catch (Exception exception)
        {
            connection.Close();
            connection = null;
        }
    }
    return connection;
}
Run Code Online (Sandbox Code Playgroud)

我发现了一篇MS Connect文章,该文章表明,在发送EXECUTE AS LOGIN命令之前,如果先前的命令尚未终止,则会导致错误.然而,如果连接刚刚打开,怎么会这样呢?

这可能与连接池与MARS奇怪地交互有关吗?

更新:从短期来看,我们已经通过在发生这种情况时清除连接池来实现一种解决方法,以消除不良连接,因为它会不断地回复给各个用户.(现在这种情况每天发生5-10次,只有少量的同时用户,所以这很烦人.)但如果有人有任何进一步的想法,我们仍然在寻找一个真正的解决方案......

gbn*_*gbn 2

我会说这是 MARS 而不是汇集

来自“使用多个活动结果集(MARS)

  • 应用程序可以打开多个默认结果集,并且可以交错读取它们。
  • 当默认结果集打开时,应用程序可以执行其他语句(例如 INSERT、UPDATE、DELETE 和存储过程调用)。

连接池的基本形式意味着连接打开/关闭开销最小化,但任何连接(直到 MARS)在任何时间都会发生一件事。池化已经存在了一段时间并且开箱即用。

MARS(顺便说一句,我没有使用过它)为任何单个连接引入了重叠的“东西”。因此,这可能是 MARS 而不是连接池才是 2 的更大罪魁祸首。

来自“使用 EXECUTE AS 扩展数据库模拟

当使用 EXECUTE AS LOGIN 语句模拟主体时,或者在服务器范围的模块中使用 EXECUTE AS 子句模拟主体时,模拟的范围是服务器范围的。

这可以解释为什么 MARS 会导致它:2 个会话中的相同主体都运行 EXECUTE AS。那篇使用文章中可能有一些东西,或者试试这个:

IF ORIGINAL_LOGIN() = SUSER_SNAME() EXECUTE AS LOGIN = {0};
Run Code Online (Sandbox Code Playgroud)

经过反思并阅读此答案后,我不相信尝试更改一个连接中每个会话(MARS)的执行上下文是一个好主意......