2010-03-30 2 views
5

При открытии соединения с SQL Server 2005 с нашего веб-приложения, иногда мы видим эту ошибку:SQL Exception: «Контекст Impersonate Security Session» нельзя назвать в этой партии, так как одновременная партия назвал его

«IMPERSONATE Контекст безопасности сеанса "не может быть вызван в этой партии, потому что это вызвало одновременную партию.

Мы используем 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 article, который предполагает, что ошибка возникает, когда предыдущая команда еще не прекращен до того, как команда EXECUTE AS ВХОД посылается. Но как это может быть, если соединение только что было открыто?

Может ли это быть чем-то связанным с пулом соединений, взаимодействующих странно с MARS?

ОБНОВЛЕНИЕ: В краткосрочной перспективе мы применили обходной путь, очистив пул соединений, когда это происходит, чтобы избавиться от плохого соединения, поскольку в противном случае он все время обращается к различным пользователям. (Это сейчас происходит 5-10 раз в день с небольшим количеством одновременных пользователей, поэтому это довольно раздражает.) Но если у кого-то есть какие-то дальнейшие идеи, мы по-прежнему смотрим на реальное решение ...

ответ

2

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

с «Using Multiple Active Result Sets (MARS)»

  • Applications can have multiple default result sets open and can interleave reading from them.
  • Applications can execute other statements (for example, INSERT, UPDATE, DELETE, and stored procedure calls) while default result sets are open.

пулы соединений в это основная форма означает, что соединение открытия/закрытия накладных расходов сведено к минимуму, но любая связь (до MARS) имеет одно в любой момент. Объединение в течение некоторого времени и просто работает из коробки.

MARS (я не использовал его BTW) вводит перекрывающиеся «вещи» для любого отдельного соединения. Так что это, вероятно, MARS, а не пул соединений является больше виновницы 2.

От «Extending Database Impersonation by Using EXECUTE AS»

When impersonating a principal by using the EXECUTE AS LOGIN statement, or within a server-scoped module by using the EXECUTE AS clause, the scope of the impersonation is server-wide.

Это может объяснить, почему MARS является причиной его: тот же главный в 2 сессии как работает EXECUTE AS , Там может быть что-то в этой статье, использования или попробовать это:

IF ORIGINAL_LOGIN() = SUSER_SNAME() EXECUTE AS LOGIN = {0}; 

Поразмыслив и после прочтения этого ответа, Я не уверен, что пытается изменить контекст выполнения для каждой сессии (MARS) в одном соединения - хорошая идея ...

+1

Благодарим за отзыв. Я согласен с тем, что он должен иметь какое-то отношение к MARS, но, разумеется, множество наборов результатов основаны на каждом соединении? И моя связь не имеет никаких предыдущих наборов результатов, поскольку я только что открыл ее, и она «новая» (хотя и из пула). Я думаю, что в вашей второй цитате, где говорится, что «объем олицетворения является серверным», это означает только для текущего соединения. – kasey

+0

@ kasey: Я предполагаю, что одно соединение имеет много сеансов, а EXECUTE AS - за сеанс. Когда соединение повторно используется из пула, я предполагаю, что переключатель контекста все еще установлен. ччмм. Возможно, это просто пул соединений и EXECUTE AS ... Интересный вопрос у вас здесь :-) – gbn

0

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

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

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

+0

Хорошая идея, но да - у нас есть блоки try/catch, чтобы мы это сделали, плюс вы получаете другую ошибку, если вы забудете сделайте это («SEVERE ERROR», который также регистрируется SQL Server). – kasey

1

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

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