Avatar billede speedpete Nybegynder
13. juni 2007 - 13:49 Der 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.
Avatar billede thesurfer Nybegynder
13. juni 2007 - 14:18 #1
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..
Avatar billede thesurfer Nybegynder
13. juni 2007 - 14:22 #2
Eksempel med Optimistisk Offline Lock:

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.
Avatar billede thesurfer Nybegynder
13. juni 2007 - 14:23 #3
Rettelse:

4 Bruger B prøver at redigere række 1 i tabellen -> update ... where id = 12 and taeller = 2
  Virker fint da taeller stadig er 2
Avatar billede thesurfer Nybegynder
13. juni 2007 - 14:25 #4
Eksempel med Pessimistic Offline Lock:

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
Avatar billede thesurfer Nybegynder
13. juni 2007 - 14:28 #5
Hvis man bruger Pessimistic Offline Lock, kan man bruge brugerid (id på personen der indlæser rækken) i stedet for true/false..

Eksempel:

FeltNavn, FeltType:
id, autonummerering
navn, tekst
laast_af, tal/heltal


...update set laast_af = 37

Her har bruger A, med brugerid 37, låst rækken..
Avatar billede thesurfer Nybegynder
13. juni 2007 - 14:31 #6
Jeg smutter på arbejde, men er sikkert online senere i aften..

Du kan evt søge på Optimistisk Offline Lock eller Pessimistic Offline Lock på nettet..
Avatar billede pidgeot Nybegynder
13. juni 2007 - 14:34 #7
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.
Avatar billede speedpete Nybegynder
13. juni 2007 - 14:59 #8
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?
Avatar billede speedpete Nybegynder
13. juni 2007 - 15:56 #9
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?
Avatar billede speedpete Nybegynder
13. juni 2007 - 15:57 #10
Nå der var jeg vist lidt hurtigt mht Pessimistic Offline Lock: Det er jo det, tælleren er der for.
Avatar billede speedpete Nybegynder
13. juni 2007 - 15:59 #11
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?
Avatar billede michael_stim Ekspert
13. juni 2007 - 16:02 #12
Men du kan lave en vice versa hvis det hjälper. Eller må du nok lave et check.

http://dev.mysql.com/doc/refman/4.1/en/insert-on-duplicate.html
Avatar billede pidgeot Nybegynder
13. juni 2007 - 17:37 #13
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).
Avatar billede speedpete Nybegynder
13. juni 2007 - 19:54 #14
Faldt lige over ObjectDataSource.ConflictDetection Property: http://msdn2.microsoft.com/en-US/library/system.web.ui.webcontrols.objectdatasource.conflictdetection.aspx
så det vil jeg lige tjekke. Ved første øjekast ser det ud til at gøre alt det ovenstående.
Avatar billede thesurfer Nybegynder
13. juni 2007 - 20:04 #15
Ang 13/06-2007 15:57:39:

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):

http://dev.mysql.com/doc/refman/4.1/en/replace.html

Det kræver at databasen understøtter REPLACE..
Avatar billede thesurfer Nybegynder
13. juni 2007 - 20:08 #16
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?
Avatar billede speedpete Nybegynder
14. juni 2007 - 17:09 #17
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?
Avatar billede thesurfer Nybegynder
14. juni 2007 - 20:37 #18
Hmm.. Jeg har godt nok ikke prøvet at bruge et gridview sammen med en database..

Måske kunne du bruge mønstret "Row Data Gateway".

Det går ud på, at du opretter et objekt, der nøjagtigt ligner din række i databasen.
Felterne i databasen bliver til attributter i objektet..

Eksempel:

class raekke
{
  private int id;
  private string navn;

  public Raekke(int id, string navn)
  {
    this.id = id;
    this.navn = navn;
  }
}

I dette eksempel, har vi en database, der indeholder 2 felter: id, navn

Koden ligner dette:

// Her åbener forbindelsen til databasen, og afvikler SQL sætningen..
// Her behandler vi de data der kommer tilbage:

// Hvis der er poster, udfør følgende:

int id = int.Parse(rs[0].ToString());
string navn = rs[1].ToString();

// luk forbindelsen til databasen

// opret objektet:
Raekke r = new Raekke(id, navn);

// Returner objektet:
return r;


Det forudsætter, at man kan binde gridview'et til et objekt, i stedet for databasen..


PS: Koden er skrevet direkte ind på eksperten, så den er ikke testet.. :-)
Avatar billede speedpete Nybegynder
15. juni 2007 - 08:21 #19
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?
Avatar billede thesurfer Nybegynder
15. juni 2007 - 17:59 #20
Det må jeg indrømme, at jeg ikke ved..

Hvis den ryger, skal du højst sandsynligt selv programmere/finde en sorteringsalgoritme.. med mindre at man kan bruge en eller anden form for array..
Avatar billede thesurfer Nybegynder
25. juni 2007 - 03:05 #21
speedpete> Er du kommet videre?
Avatar billede speedpete Nybegynder
25. juni 2007 - 08:10 #22
øh, næ... undskyld. Har lagt det lidt på hylden, idet kravspec. ændrede sig.
Avatar billede thesurfer Nybegynder
27. juli 2007 - 10:51 #23
Hvad er de nye kravspecifikationer så? :-)
Avatar billede speedpete Nybegynder
27. juli 2007 - 13:08 #24
Ja... det er endt med at jeg bruger det indbyggede Optimistic Concurrency i DataSourcen og lader det ligge ved det.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester