Blokowanie odczytu z tabeli bazy danych

2

Buduję aplikację w c# z połączeniem do bazy MS SQL 2012. Chcę zrobić tak:
Kiedy mam otwarte okienko z edycją danych klienta, przy próbie edycji danych tego samego klienta na innym komputerze w sieci lokalnej, pokazuje się informacja - Klient jest już edytowany.

0

Najprostszy pomysł kolumna z flagą IsEdit? I na tej podstawię sprawdzasz.
Inny ale głupi pomysł, robić locki na wierszach. Patrz hasło ROWLOCK. Tam poczytasz czemu tego nie robić:)

0

możesz podać jakieś za, że stosowanie locków na wierszach to głupi pomysł??? Bo jak na razie to głupia to jest twoja wypowiedź.

@dziubasek1 co do pytania to poczytaj o pesymistycznym blokowaniu (dla kontrastu możesz też poczytać o blokowaniu optymistycznym)

0

Blokowanie wierszy powinna zajmować się logika SQL i sesje z tym związane. Nieumiejętne wymuszanie blokowanie danego wiersza może powodować blokowanie innych tranzakcji, nawet tych z odczytem. W tak prostym przypadku jak wyżej dużo zaproponowane przez mnie rozwiązanie w zupełności wystarczy. Nazywam takie rozwiązanie głupim gdyż tworzy moim zdaniem zbyt wiele potencjalnych problemów i jest to przerost formy nad treścią.

2

Z tego co udało mi się zorientować, to:

  • ROWLOCK może powodować błędy w działaniu transakcji,
  • przy zastosowaniu podejścia pesymistycznego konieczne jest utrzymywanie stałego połączenia z bazą.

Myślę, że dobrym rozwiązaniem może być stworzenie specjalnej tabeli, której każdy wiersz będzie przechowywał informacje takie jak nazwa edytowanej tabeli, Id edytowanego wiersza, nazwa hosta, na którym uruchomiono edycję. Wtedy przy edycji danych klienta do tej tabeli będzie dodawany wpis z informację o edytowanym wierszu, co zablokuje możliwość podwójnej edycji (przy próbie otwarcia oka z edycją będzie sprawdzane czy w specjalnej tabeli wiersz nie jest zablokowany) tego samego wiersza w tym samym czasie. Tabla będzie czyszczona przy każdym zamknięciu oka z edycją, logowaniu do aplikacji. Dodatkowo w opcjach programu można dodać funkcję czyszczenia specjalnej tabeli z opcjami: czyść całą, tylko blokady założone przez hosta - w celu możliwość usunięcia blokad w przypadku wystąpienia niekontrolowanego zamknięcia aplikacji.

0

@dziubasek1,

ok lecz nadal nie chroni nas to przed pozostawionym lock'iem w momencie gdy aplikacja się wywróci lub np braknie prądu. Twoje rozwiazanie usunie locki przy następnym uruchomieniu aplikacji, co jeśli ktoś już jej nie uruchomi?

przydałoby się finally w transakcjach, niestety z tego co wiem nie ma takiej opcji...

1

Znalazłem coś co może być interesujące.
sp_getapplock oraz sp_releaseapplock

Applock zakładamy na 'resource' w postaci ciągu znaków (taki trochę .NETowy lock(object){}). Tworząc go zmyślnie (np nazwa_tabeli+id wiersza) możemy uzyskać fajny mechanizm blokowania wiersza.
Z tego co czytam, to sp_getapplock jest wiązany do transakcji lub sesji, jeśli nie zostanie explicite zdjęty (releaseapplock) to jest zdejmowany automagicznie gdy kończy się transakcja/sesja.

W przypadku gdy jesteśmy w transakcji i aplikacja się wywróci, zrobi się rollback i lock zostanie zdjęty.
Zastanawiające jest tylko co jeśli nie będziemy w transakcji (nikt nie będzie otwierał transakcji na cały okres edycji wiersza poprzez np formularz). Jak rozumieć sesję w SQL Server biorąc pod uwagę ADO .NET i connection pooling? Teoretycznie w momencie gdy aplikacja się wywróci, połączenie jest zrywane, sesja zamykana i lock zwalniany. Pozostaje doszukać się gdzieś tego lub przetestować :)

Tutaj więcej szczegółów:

http://technet.microsoft.com/en-us/library/ms189823.aspx
http://technet.microsoft.com/pl-pl/library/ms178602.aspx

http://stackoverflow.com/questions/7515797/sql-server-session
http://stackoverflow.com/questions/2726314/release-another-users-lock-obtained-with-sp-getapplock-on-sql-server

Sorry za post pod postem ale chciałem żeby temat poleciał do góry

1 użytkowników online, w tym zalogowanych: 0, gości: 1