1

При попытке установить роль приложения на SqlConnection с sp_setapprole я иногда получаю следующее сообщение об ошибке в журнале событий Windows ...Обнаружение непригодные объединенные SqlConnections

Соединение уронили, так как основной, который открыл впоследствии он принял новый контекст безопасности, а затем попытался сбросить соединение под своим олицетворенным контекстом безопасности. Этот сценарий не поддерживается. См. «Обзор олицетворения» в электронной документации.)

... и соответствующее исключение выбрано в моем приложении.

Они объединяют соединения, и было время, когда пул соединений несовместим с ролями приложения - на самом деле старый совет от Microsoft был disable connection pooling (!!), но с введением sp_unsetapprole сейчас (в теории) можно очистить соединение, прежде чем возвращать его в пул.

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

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

Возможно ли выявить проблему, не вызывая исключения?

Мысли или совет добро пожаловать.

ответ

1

Это происходит по логике и не имеет большого опыта использования sp_setapprole, но разве не удалось бы проверить контекст безопасности перед выполнением вызова? Или, альтернативно, сначала проверьте разрешение и контекст безопасности?

+0

Насколько я знаю, невозможно выполнить НИКАКОЙ sql-код в непригодном для использования соединении без исключения исключения. Поэтому я не могу допросить соединение, чтобы проверить контекст безопасности. –

+0

Достаточно честный. Тогда поцарапайте эту идею. Однако не можете ли вы выполнить проверку другого соединения или это повлияет на все приложение? – BinaryMisfit

+0

Это пул подключения, поэтому, хотя я могу получить другое соединение, я не мог допросить состояние первого соединения с ним. Все, что у меня есть, это соединение, которое может или не может быть использовано, я не знаю, пока не попытаюсь его использовать. –

1

Казалось бы, вы вызываете sp_setapprole, но не вызываете sp_unsetapprole, а затем разрешаете соединение просто возвращаться в пул.

Я хотел бы предложить использовать структуру (или класс, если вы должны использовать это через методы) с реализацией IDisposable, который будет заботиться об этом для Вас:

public struct ConnectionManager : IDisposable 
{ 
    // The backing for the connection. 
    private SqlConnection connection; 

    // The connection. 
    public SqlConnection Connection { get { return connection; } } 

    public void Dispose() 
    { 
     // If there is no connection, get out. 
     if (connection == null) 
     { 
      // Get out. 
      return; 
     } 

     // Make sure connection is cleaned up. 
     using (SqlConnection c = connection) 
     { 
      // See (1). Create the command for sp_unsetapprole 
      // and then execute. 
      using (SqlCommand command = ...) 
      { 
       // Execute the command. 
       command.ExecuteNonQuery(); 
      } 
     } 
    } 

    public ConnectionManager Release() 
    { 
     // Create a copy to return. 
     ConnectionManager retVal = this; 

     // Set the connection to null. 
     retVal.connection = null; 

     // Return the copy. 
     return retVal;   
    } 

    public static ConnectionManager Create() 
    { 
     // Create the return value, use a using statement. 
     using (ConnectionManager cm = new ConnectionManager()) 
     { 
      // Create the connection and assign here. 
      // See (2). 
      cm.connection = ... 

      // Create the command to call sp_setapprole here. 
      using (SqlCommand command = ...) 
      { 
       // Execute the command. 
       command.ExecuteNonQuery(); 

       // Return the connection, but call release 
       // so the connection is still live on return. 
       return cm.Release(); 
      } 
     } 
    } 
} 
  1. Вы создать SqlCommand, который соответствует вызову хранимой процедуры sp_setapprole. Вы можете сгенерировать файл cookie и сохранить его в частной переменной-члене.
  2. Здесь вы можете создать свое соединение.

код Клиент будет выглядеть следующим образом:

using (ConnectionManager cm = ConnectionManager.Create()) 
{ 
    // Get the SqlConnection for use. 
    // No need for a using statement, when Dispose is 
    // called on the connection manager, the connection will be 
    // closed. 
    SqlConnection connection = cm.Connection; 

    // Use connection appropriately. 
} 
+0

Я вызываю unsetapprole, этот вопрос касается того, можно ли определить сценарий, в котором он не был вызван. –

1

Это немного грязно, но если ваш первоначальный пользователь имеет права на VIEW SERVER STATE, select * from sys.sysprocesses будет возвращать все процессы, когда роль не активна, и одну строку для текущего процесса, если она есть.

Смежные вопросы