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次,只有少量的同时用户,所以这很烦人.)但如果有人有任何进一步的想法,我们仍然在寻找一个真正的解决方案......
我会说这是 MARS 而不是汇集
来自“使用多个活动结果集(MARS) ”
- 应用程序可以打开多个默认结果集,并且可以交错读取它们。
- 当默认结果集打开时,应用程序可以执行其他语句(例如 INSERT、UPDATE、DELETE 和存储过程调用)。
连接池的基本形式意味着连接打开/关闭开销最小化,但任何连接(直到 MARS)在任何时间都会发生一件事。池化已经存在了一段时间并且开箱即用。
MARS(顺便说一句,我没有使用过它)为任何单个连接引入了重叠的“东西”。因此,这可能是 MARS 而不是连接池才是 2 的更大罪魁祸首。
当使用 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)的执行上下文是一个好主意......