2012-01-26 6 views
7

Questo è il codice che ho.C'è già un DataReader aperto associato a questo comando che deve essere chiuso prima

/// <summary> 
/// Method calls stored procedure and fills DataSet of contacts associated with Lead 
/// </summary> 
/// <param name="leadID">The ID associated with a Lead</param> 
/// <returns>contacts list as DataSet</returns> 
public static DataSet GetContactResultSetByLead(int leadID) 
{ 
    SqlCommand Sqlmd = new SqlCommand("dbo.proc_contact"); 
    Sqlmd.CommandType = CommandType.StoredProcedure; 
    Sqlmd.Parameters.Add("@LeadInfoID", SqlDbType.Int).Value = leadID; 

    Sqlmd.Connection = m_ConStr; 
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd); 

    DataSet data = new DataSet(); 
    try 
    { 
     da.Fill(data); 
    } 

    finally 
    { 
     m_ConStr.Close(); 
    } 

    return data; 
} 
+0

Che cos'è 'm_ConStr'? –

+0

modificare questa riga Sqlmd.Parameters.Add ("@ LeadInfoID", SqlDbType.Int) .Value = leadID; a Sqlmd.Parameters.AddWithValue ("@ LeadInfoID", leadID); Se si desidera mantenere il Global Connect, verificare lo stato di tale connessione se è aperto, quindi chiuderlo prima di utilizzarlo. REFATTORE IL TUO CODICE E UTILIZZA NOMI VARIABILI SIGNIFICATIVI ....! Racchiudere la connessione con un() {} – MethodMan

+1

Sqlmd verrà eseguito durante la chiamata da.Fill. m_ConStr sembra essere una variabile con un nome errato - sembra riferirsi alla connessione stessa, non alla stringa di connessione. – RQDQ

risposta

9

Il tuo problema è che apparentemente hai un'istanza di m_ConStr; se il metodo viene chiamato contemporaneamente, solo uno di questi sarà in grado di utilizzare la connessione e l'altro fallirà con l'eccezione che si sta ricevendo.

Utilizzare questo modello invece:

using (SqlConnection conn = new SqlConnection()) 
{ 
    conn.Open(); 
    Sqlmd.Connection = conn; 
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd); 
    //...etc 
} 

In altre parole, non definiscono connessione come una variabile globale alla classe.

+0

"non definire la connessione come variabile globale": ma come evitare di creare e aprire una connessione ogni volta che devo eseguire una sp. Nel mio caso devo eseguire un sacco di sp, e senza instanciare una connessione, l'alternativa è creare e aprire ogni volta. Qualche suggerimento? – ff8mania

1

Stai cercando di eseguire più set di risultati actice (aka MARS).

Due possibili soluzioni vengono in mente:

  1. aperto aperto una nuova connessione in GetContractResultSetByLead
  2. Attiva MARS sul server di database (descritto nel link qui sotto).
+0

Puoi anche provare ad aggiungere questo nella web.config nella stringa di connessione: connectionString = "MultipleActiveResultSets = True; user = ..." – Nestor

5

suggerisco È possibile utilizzare il blocco per garantire un corretto smaltimento di sqlconnection.

using (SqlConnection conn = new SqlConnection()) 
{ 
    conn.Open(); 
    Sqlmd.Connection = conn; 
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd); 
    Dataset ds = new Datasest 
    da.Fill(ds) 
} 

l'altro modo è possibile anche impostare la proprietà MARS nella connessione, se necessario.

SqlConnection m_ConStr;= new SqlConnection("Server= serverName;Database=yourDatabase; 
     MultipleActiveResultSets=true;"); 
+2

La connessione deve essere dichiarata localmente (si verificheranno tutti i tipi di effetti collaterali se si utilizza un'istanza condivisa). Inoltre, perché non dovresti semplicemente utilizzare un'istruzione using per gestire la durata della connessione? – RQDQ

+1

questo è anche un buon suggerimento :) ok lo modificherò :) –

+1

Grazie mille – Marcus3329

5

Tutti i tuoi oggetti di breve durata IDisposable mancano di un "utilizzo". Per estensione, quindi, è possibile che tu abbia fatto qualcosa del tipo:

var reader = anotherCommand.ExecuteReader(); 
... 

Ma questo non dispone/chiude il lettore. Se questo è il caso, aggiungi "using":

using(var reader = anotherCommand.ExecuteReader()) { 
    ... 
} 

Che chiude il lettore, indipendentemente da come usciamo. I comandi, le connessioni, i lettori e le transazioni sono tutti usa e getta e tutti dovrebbero solitamente usare "usando".