2013-09-25 11 views
6

Jeśli mam funkcję, która edytuje bazę danych w moim serwisie internetowym, chcę, aby jeden wątek był uruchamiany za jednym razem, jeśli próbują edytować ten sam wiersz.Zablokować tylko, jeśli wartość jest taka sama?

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

wiem, że może zablokować całą funkcję, ale wtedy stracę ponoszeniu ponieważ jej prawie nigdy, że różne wątki spróbuje edytować ten sam czek.

Czy istnieje sposób na zablokowanie innych wątków z tym samym checkidem?

UPDATE

użyć OleDbConnection i MySqlConnection

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

taka sama funkcja MySqlCommand

a potem jus użyciu normalnych wkładkę i SQL UPDATE poleceń. i transakcja jest sprawdzana, czy jest obecna, czy nie. więc ta funkcja działa, jeśli chcesz transakcji, lub nie, w funkcji wyższego poziomu.

do odczytu z bazy danych będę wypełniać 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

Czy nie powinno to być obsługiwane na końcu bazy danych? Czy masz problem lub czy jest to oparte na założeniach? –

+0

W jaki sposób jest zapisywany dostęp do danych? Jeśli używasz EF, może to pomóc: http: //blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concrency-in-the- entity-framework.aspx – Lev

+1

Czy możesz pokazać, w jaki sposób uzyskujesz dostęp do bazy danych, istnieją dobre narzędzia wbudowane w wiele metod dostępu do danych w celu rozwiązania tego problemu (każde rozwiązanie działające tylko po stronie klienta działałoby tylko wtedy, gdy tylko jeden klient kiedykolwiek łączy się z bazą danych Jeśli dwie kopie twojego programu wywołają "EditCheck" dla tego samego "checkid", bieżące odpowiedzi nie zadziałają) –

Odpowiedz

13

Można użyć ConcurrentDictionary mapować każdy identyfikator obiektu, który można zablokować na:

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

ładny.poprawa w stosunku do [tej odpowiedzi] (http://stackoverflow.com/a/781324/571637) – jltrem

+0

Dziękuję za odpowiedź, przeczytam na ConcurrentDictionary i przetestuję to. Ale wygląda na to, czego potrzebuję. – Dendei

+0

Możesz również zajrzeć do opcji [ReadWriterLock] (http://stackoverflow.com/questions/2116957/readerwriterlock-vslock), jeśli zamierzasz mieć wiele wątków wykonujących tylko operacje tylko do odczytu na 'checkid' w tym samym czasie, pozwoli to wielu wątkom wszystkie wykonywać operacje odczytu na tym samym' checkid', ale gdy ktoś chce je zapisać, blokuje wszystkie współbieżne czytniki. –

0

, jak chcesz poprawić wydajność, w ostatniej chwili powinieneś zrobić blokowanie. Podczas korzystania z bazy danych można korzystać z blokowania DB. Masz dwie opcje:

  1. Zastosowanie Select for update, spojrzeć na Proper way to SQL select and update
  2. Korzystanie z optymistycznego blokowania, który jest IMHO najlepszym sposobem, aby to zrobić, http://en.wikipedia.org/wiki/Optimistic_concurrency_control lub http://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html

Zauważ, że oba podejścia pozwala na korzystanie z DB zasoby bardziej niż programowe. To jest lepsze, niż proponowany słownik, dlaczego?

Po skopiowaniu danych te w DB są duplikowane w słowniku środowiska wykonawczego, użytkownik jest zmuszony je zsynchronizować, więc jeśli ktoś aktualizuje bazę danych i dodaje nową id, należy natychmiast zaktualizować słownik.

Oczywiście, jest to możliwe w przypadku małej klasy (np. Repozytorium), ale gdy projekt się rozrośnie, niektórzy koledzy mogą zapomnieć o tych informacjach i zaczną znajdować takie błędy.

Powiązane problemy