5

从我们的 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;
}

我发现了一篇MS Connect 文章,该文章表明该错误是由于在发送 EXECUTE AS LOGIN 命令之前之前的命令尚未终止而引起的。然而,如果连接刚刚打开,这怎么可能呢?

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

更新:在短期内,我们通过在发生这种情况时清除连接池来实现一种解决方法,以摆脱不良连接,否则它会不断交还给各种用户。(现在这种情况每天发生 5-10 次,只有少数同时用户,所以这很烦人。)但是如果有人有任何进一步的想法,我们仍在寻找真正的解决方案......

4

3 回答 3

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};

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

于 2010-03-30T18:17:28.230 回答
2

不要责怪连接池——MARS 因造成严重破坏而臭名昭著。这不完全是它的责任,但它有点一半一半。要记住的关键是 MARS 是经过设计的,并且仅适用于“正常”数据库使用(意思是常规 CRUD 内容,没有管理批处理)。任何对数据库引擎有广泛影响的命令都可能触发 MARS,即使它只是一个连接和单线程(例如运行设置批处理来创建表或嵌套事务)。

话虽如此,人们可以很容易地责怪 MARS,但它对于 99% 左右的普通 CRUD 场景非常有效(并且像 ORM-s 和 LINQ 这样的低效率的东西终生依赖它)。这意味着人们必须了解,如果他们想通过连接破解 SQL,他们就不能使用 MARS。例如,我有一个从头开始创建整个数据库的设置代码,因为它非常便于部署,但它与正在部署的 Web 服务共享连接 sting - 哎呀 :-) 我花了几天时间挖掘来学习我的课程. 所以我只是保持关注点的分离(这总是好的),问题就消失了。

于 2010-08-06T11:12:17.793 回答
0

您是否尝试在 sql 语句的末尾使用还原?

http://msdn.microsoft.com/en-us/library/ms178632.aspx

我总是这样做只是为了确保当前环境恢复正常。

于 2010-08-05T12:52:00.513 回答