2013-09-25 9 views
6

Se ho una funzione che modifica il database nel mio webservice, desidero eseguire un solo thread alla volta se provano a modificare la stessa riga.Blocca solo se il valore è lo stesso?

void EditCheck(long checkid) 
    { 

     if (isCheckCosed) 
      throw new Exception("check is already closed"); 

     //do stuff 

     //after i edit my check i want to close it. 
     CloseCheck(); 
    } 

so di poter bloccare l'intera funzione, ma poi ho sciolto preformance perché la sua quasi mai che diversi thread cercheranno di modificare lo stesso controllo.

c'è un modo per bloccare solo altri thread che hanno lo stesso check-in?

UPDATE

i utilizzare OleDbConnection e MySqlConnection

OleDbCommand oleDbCommand = AccessTrans != null ? 
new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn); 
oleDbCommand.ExecuteNonQuery(); 

la stessa funzione per MySqlCommand

e quindi i ius utilizzare i normali comandi INSERT e UPDATE SQL. e la transazione viene controllata se è presente o meno. quindi questa funzione funziona se vuoi una transazione o meno nella tua funzione di livello superiore.

per la lettura dal database ve lo riempirò DataTable

OleDbCommand oleDbCommand = AccessTrans != null ? new OleDbCommand(sql, AccessConn, AccessTrans) : new OleDbCommand(sql, AccessConn); 
OleDbDataAdapter dAdapter = new OleDbDataAdapter(); 
dAdapter.SelectCommand = oleDbCommand; 
dAdapter.Fill(dTable); 
return dTable; 
+2

Non dovrebbe essere gestito sul database? Hai effettivamente un problema o si basa solo su ipotesi? –

+0

Come viene scritto l'accesso ai dati? Se stai usando EF questo può aiutare: http: //blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the- entity-framework.aspx – Lev

+1

Puoi mostrare come stai accedendo al database, ci sono buoni strumenti incorporati in molti metodi di accesso ai dati per gestire questo problema (qualsiasi soluzione sul lato client funzionerebbe solo se solo un client si collegasse al database Se due copie del tuo programma chiamano entrambi "EditCheck" per lo stesso 'checkid', le risposte attuali non funzionerebbero) –

risposta

13

È possibile utilizzare un ConcurrentDictionary per mappare ogni ID a un oggetto che è possibile bloccare il:

public class Foo 
{ 
    private ConcurrentDictionary<long, object> dictionary = 
     new ConcurrentDictionary<long, object>(); 

    private void EditCheck(long checkid) 
    { 
     var key = dictionary.GetOrAdd(checkid, new object()); 
     lock (key) 
     { 
      //Do stuff with key 
     } 
    } 
} 
+0

bello.un miglioramento rispetto a [questa risposta] (http://stackoverflow.com/a/781324/571637) – jltrem

+0

Grazie per la risposta, leggerò ConcurrentDictionary e testarlo. Ma sembra proprio quello di cui ho bisogno. – Dendei

+0

Si potrebbe anche voler utilizzare un [ReadWriterLock] (http://stackoverflow.com/questions/2116957/readerwriterlock-vs-lock) se si stanno avendo molti thread che fanno solo operazioni di sola lettura sul 'checkid' allo stesso tempo, questo permetterà a più thread di eseguire operazioni di lettura sullo stesso' checkid', ma una volta che qualcuno vuole scriverlo blocca tutti i lettori concorrenti. –

0

come si vuole migliorare le prestazioni, dovresti fare il blocco al momento più recente possibile. Quando si utilizza il database, è possibile utilizzare il blocco DB. Hai due opzioni:

  1. Usa Select for update, guarda Proper way to SQL select and update
  2. Usa blocco ottimistico che è IMHO approccio migliore per farlo, http://en.wikipedia.org/wiki/Optimistic_concurrency_control o http://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html

Si noti che entrambi gli approcci consente di utilizzare DB risorse più di quelle programmatiche. Questo è meglio di quel dizionario proposto, perché?

Una volta duplicati i dati, quelli in DB sono duplicati nel dizionario di runtime, è necessario sincronizzarli, quindi se qualcuno aggiorna il database e aggiunge nuovo id è necessario aggiornare immediatamente il dizionario.

Certo, è fattibile per piccole classi di mantenimento (ad esempio repository) ma una volta che il progetto si sviluppa, alcuni dei tuoi colleghi possono dimenticare queste informazioni e inizierai a trovare questo tipo di bug.

Problemi correlati