Исключение SQL: «Олицетворять контекст безопасности сеанса» нельзя вызвать в этом пакете, потому что его вызвал одновременный пакет - PullRequest
5 голосов
/ 30 марта 2010

При открытии соединения с 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 раз в день с небольшим количеством одновременных пользователей, поэтому это довольно раздражает.) Но если у кого-то есть какие-то дальнейшие идеи, мы все еще ищем реальное решение ...

Ответы [ 3 ]

2 голосов
/ 06 августа 2010

Не вините пул соединений - MARS довольно печально известен тем, что наносит ущерб. Это не совсем вина, но это наполовину. Главное, что нужно помнить, это то, что MARS спроектирован и работает только с «обычным» использованием БД (имеется в виду, обычные вещи CRUD без администраторских пакетов). Любые команды, которые имеют большое влияние на механизм БД, могут отключить MARS, даже если это только одно соединение и однопоточное (например, запуск пакета установки для создания таблиц или вложенная транзакция).

Сказав это, можно легко обвинить MARS, но он прекрасно работает для нормальных сценариев CRUD, которые подобны 99% (и вещи с низкой эффективностью, такие как ORM-s и LINQ, зависят от него на всю жизнь). Это означает, что людям важно понять, что если они хотят взломать SQL через соединение, они не могут использовать MARS. Например, у меня был установочный код, который создавал целую БД с нуля, потому что она очень удобна для развертывания, но она делилась связующим звеном с веб-службой, которую развертывал - упс :-) У меня ушло несколько дней на копание, чтобы выучить мой урок , Поэтому я просто поддерживаю разделение интересов (что всегда хорошо), и проблемы исчезли.

2 голосов
/ 30 марта 2010

Я бы сказал, что это MARS, а не объединение

Из " Использование нескольких активных наборов результатов (MARS) "

  • Приложения могут иметь несколько значений по умолчанию наборы результатов открыты и могут чередоваться читаю из них.
  • Приложения могут выполнять другие операторы (например, ВСТАВИТЬ, ОБНОВИТЬ, УДАЛИТЬ и сохранить вызовы процедур) пока результат по умолчанию наборы открыты.

Пул соединений в его основной форме означает, что издержки на открытие / закрытие соединения минимизированы, но любое соединение (до 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) в одном соединении - хорошая идея ...

0 голосов
/ 05 августа 2010

Вы пытались использовать возврат в конце вашего оператора SQL?

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

Я всегда делаю это, чтобы убедиться, что текущий контекст вернулся к нормальному.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...