2010-03-30 13 views
5

Quando si apre una connessione a SQL Server 2005 dal nostro web app, che di tanto in tanto vediamo questo errore:SQL Eccezione: "Rappresenta Sessione contesto di protezione" non può essere chiamato in questo gruppo perché un lotto simultanea ha chiamato

"Rappresenta Session Security Context "non può essere chiamato in questo batch perché è stato chiamato da un batch simultaneo.

Utilizziamo MARS e il pool di connessioni.

L'eccezione proviene dalla seguente pezzo di codice:

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

Ho trovato un MS Connect article che suggerisce che l'errore è causato quando un comando precedente non è ancora terminato prima EXECUTE AS LOGIN comando viene inviato. Ma come può essere questo se la connessione è stata appena aperta?

Questo potrebbe essere qualcosa a che fare con il pool di connessioni che interagiscono stranamente con MARS?

AGGIORNAMENTO: Per il breve termine abbiamo implementato una soluzione eliminando il pool di connessioni ogni volta che ciò accade, per sbarazzarsi della connessione errata, in quanto altrimenti viene sempre restituita a vari utenti. (Questo accade ora 5-10 volte al giorno con solo un piccolo numero di utenti simultanei, quindi è abbastanza fastidioso.) Ma se qualcuno ha altre idee, stiamo ancora cercando una soluzione reale ...

risposta

2

direi che è MARS piuttosto che mettere in comune

Da "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.

il pool di connessioni nella sua forma di base si intende la connessione di apertura/chiusura testa è ridotto al minimo, ma qualsiasi connessione (fino MARS) ha una cosa andando avanti in qualsiasi momento. Il pooling è in circolazione da un po 'di tempo e funziona appena fuori dagli schemi.

MARS (non l'ho usato BTW) introduce una "roba" sovrapposta in corso per ogni singola connessione. Quindi è probabilmente MARS piuttosto che il pool di connessioni è il più grande colpevole del 2.

Da "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.

Questo potrebbe spiegare perché MARS è la causa: lo stesso principio in 2 sessioni entrambi in esecuzione EXECUTE AS . Ci può essere qualcosa in quel articolo di uso, o di provare questo:

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

Riflettendoci e dopo aver letto questa risposta, ho convinto che cercando di cambiare contesto di esecuzione per ogni sessione (MARS) in una le connessioni sono una buona idea ...

+1

Grazie per la risposta. Sono d'accordo che deve avere qualcosa a che fare con MARS, ma sicuramente i set di risultati multipli sono su una base per connessione? E la mia connessione non ha precedenti set di risultati, perché l'ho appena aperta ed è "nuova" (anche se dal pool). Penso che nella tua seconda citazione dov'è scritto "lo scopo della rappresentazione è esteso al server", significa solo per la connessione corrente. – kasey

+0

@kasey: la mia ipotesi è che la singola connessione abbia molte sessioni e che EXECUTE AS sia per sessione. Quando una connessione viene riutilizzata dal pool, suppongo che l'interruttore di contesto sia ancora impostato. hhmm. Forse è solo il pool di connessioni e l'ESEGUI AS ... Interessante domanda che hai qui :-) – gbn

0

Hai provato a utilizzare un ripristino alla fine della tua istruzione sql?

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

faccio sempre questo per fare solo che il contesto attuale è tornato alla normalità.

+0

Buona idea ma sì - abbiamo provato/catturare i blocchi per assicurarci di farlo, inoltre ottieni un diverso tipo di errore se ti dimentichi di fallo (un 'SEVERE ERROR' che viene registrato anche da SQL Server). – kasey

1

Non incolpare il pool di connessioni - MARS è piuttosto noto per provocare il caos. Non è colpa di tutti, ma è metà e metà.La cosa fondamentale da ricordare è che MARS è stato progettato e funziona solo con l'utilizzo di DB "normale" (ovvero, roba regolare di CRUD senza batch di amministratore). Qualsiasi comando che abbia un ampio effetto sul motore DB può far scattare MARS anche se è solo una connessione e un singolo thread (come l'esecuzione di un batch di installazione per creare tabelle o una transazione nidificata).

Detto questo, si può facilmente incolpare MARS, ma funziona perfettamente bene per normali scenari CRUD che sono come il 99% (e cose con bassa efficienza come ORM-se LINQ dipendono da esso per tutta la vita). Significa che è importante per le persone imparare che se vogliono hackerare SQL attraverso una connessione non possono usare MARS. Ad esempio, avevo un codice di installazione che creava tutto il DB da zero, perché è molto comodo per l'implementazione, ma stava condividendo la connessione con il servizio Web che stava implementando - oops :-) Ci sono voluti alcuni giorni di scavo per imparare la lezione . Quindi mantengo solo la separazione delle preoccupazioni (che è sempre buona) e i problemi sono andati via.

Problemi correlati