13. juni 2007 - 13:49Der er
23 kommentarer og 1 løsning
flere brugere : create, read, update, delete
Jeg skal lave et system, hvor folk logger sig på (via .net20's indbyggede Memberhip framework). De skal så have lov til at læse og redigere i nogle MySQL-datatabeller via GridView.
Hvordan sikrer jeg (med synkronisering, låsning, eller på anden måde), at følgende ikke sker:
1 Bruger A ser tabellen. 2 Bruger B ser tabellen. 3 Bruger A sletter række 1 i tabellen. 4 Bruger B prøver at redigere række 1 i tabellen... men han ved ikke, at den er blevet slettet i punkt 3.
Du kan bruge Optimistisk Offline Lock eller Pessimistic Offline Lock..
Man har et felt, der indeholder en tæller/datotid, som systemet får udleveret, ved SELECT sætningen. Denne værdi (tæller/datotid) skal matche, når skal opdatere databasen..
FeltNavn, FeltType: id, autonummerering navn, tekst taeller, tal/heltal
Lad os antage, at værdierne er således: 12 hans 0
1 Bruger A ser tabellen -> taeller = taeller + 1 (nu er værdien: 1) 2 Bruger B ser tabellen -> taeller = taeller + 1 (nu er værdien: 2) 3 Bruger A sletter række 1 i tabellen -> delete from tabel where id = 12 and taeller = værdi (som jo er 1) FEJL FEJL FEJL! værdi er jo ikke længere 1, så rækken kan ikke slettes 4 Bruger B prøver at redigere række 1 i tabellen... men han ved ikke, at den er blevet slettet i punkt 3.
FeltNavn, FeltType: id, autonummerering navn, tekst laast, true/false
Lad os antage, at værdierne er således: 12 hans false
1 Bruger A ser tabellen -> update tabel set laast = true where id = 12 2 Bruger B ser tabellen -> da laast er TRUE, kan B ikke læse FEJL FEJL FEJL 3 Bruger A sletter række 1 i tabellen.
Da A har slette rækken, findes den ikke mere.
Hvis A bare opdaterer rækken, ser det sådan ud:
update tabel set navn = 'jensen', laast = false where id = 12
Jeg ville nu nok snarere implementere optimistisk låsning så A godt kunne få lov til at slette, men B fik en fejl når han så ville redigere. Det virker mere naturligt, og man slipper for at holde styr på en tæller, og det kan implementeres så de kan ændre to forskellige ting i samme record på samme tid.
Måden man gør det på er grundlæggende at man gemmer en kopi af recorden ved siden af den man ændrer i, for så at kontrollere hvor der er sket ændringer inden man committer. Hvis et af de felter brugeren har ændret i også er anderledes nede i databasen, får han en fejl.
tak tak, jeg prøver at surfe lidt på Optimistisk Offline Lock. I mellemtiden: Jeg kan ikke lige gennemskue, om det løser hele rækken af problemer mht. insert, update og delete?
Mht. Optimistic Offline Lock: 1 Bruger A begynder at editere en række 2 Bruger B sletter den samme række 3 Bruger A forsøger at committe sine ændringer, og systemet forsøger at sammenligne den kopi af rækken, som det har gemt, med den række som nu står i databasen for at se, om den er ændret. Men rækken er jo lige blevet slettet!
Mht. Pessimistic Offline Lock: Hvis A læser en række og skriver en lås på rækken, og så afslutter sin session uden at fjerne låsen, hvordan får man så fjernet låsen igen?
Eller kunne man alternativt tænke sig, at hvis man forsøger at UPDATE og rækken i mellemtiden er slettet, så håndterer man fejlen fra databasen ved at lave UPDATEN om til en INSERT?
Mht. hvordan du håndterer sletningen i optimistisk låsning, så afhænger det jo af hvordan du vil have det skal fungere.
Systemet kan jo se at rækken ikke findes i det den forsøger at køre UPDATE'n, og det kan du så håndtere på den måde der nu passer bedst til det du laver - dvs. du enten smider en fejl tilbage til brugeren, sætter rækken ind på normal vis (evt. med INSERT ON DUPLICATE, hvis MySQL er ny nok), eller spørger brugeren hvad der skal ske (du skal i så fald samtidigt holde styr på om andre ændre mere mens brugeren beslutter sig).
Der er ikke en tæller i den pessimistiske lås. Der er kun "låst" eller "ulåst". Det er i den optimistiske lås, at der er en tæller eller et datotid-felt. Datotid-feltet virker på samme måde som tælleren: Hvis DET-JEG-HAR er lig DET-DER-ER-I-DATABASEN Gem/opdater ellers Der er en anden der har læst rækken, så jeg kan ikke gemme Slut hvis
Ang 13/06-2007 15:59:11, 13/06-2007 16:02:54 og 13/06-2007 17:37:10:
Det er også muligt at bruge REPLACE, i stedet for INSERT + UPDATE.. Men REPLACE er lidt langsommere (lidt dårligere performance/performans):
Du har ret i 13/06-2007 15:56:16, angående den pessimistiske lås..
Det er farligt at bruge pessimistisk lås.. og man skal have en eller anden metode, til at sikre sig, at vedkommende ikke bare er gået fra computeren, med dataene fremme på skærmen.
Med den optimistiske lås, ved man ikke, om det man har lavet, bliver gemt.
Valget afhænger af ens strategi.. Vil man være 100% sikker på, at man kan gemme, på bekostningen af at en bruger muligvis forlader computeren? Eller vil han håbe på, at man kan gemme?
Ok, jeg valgte den optimistiske løsning. Det er sådan set ret nemt at lave med ObjectDataSource.ConflictDetection. Så kan man i sit datalag eller businesslag detektere på antallet af berørte rækker og kaste en exception opad.
Mit eneste problem er nu mit GridView: Når man trykker på "Edit", så kommer der inputtekstbokse frem, som man kan skrive i. Problemet er, at der ikke vises de samme værdier som stod i gridviewet før man trykkede edit, men at rækken genopfriskes fra databasen. Det kan godt virke lidt forvirrende for brugeren, tænker jeg (du vil ændre teksten fra "Ostemad" til "Rejemad", men idet du trykker "Edit", så står der pludselig "Leverpostejsmad" (fordi en anden bruger i mellemtiden har ændre "Rejemad" til "Leverpostejsmad"). Hvordan styrer jeg det? Nogen bud?
Jeg vil helst se, om det kan lade sig gøre med de egenskaber, som GridView er født med. Jeg kunne forestille mig at folkene hos Microsoft trods alt har forudset situationen.
Hvis man binder GridViewet til objekter i stedet for DataTable/DataSet, så ryger den automatiske sortering vist?
Ja... det er endt med at jeg bruger det indbyggede Optimistic Concurrency i DataSourcen og lader det ligge ved det.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.