Avatar billede thepsypher Nybegynder
07. maj 2010 - 12:39 Der er 10 kommentarer og
1 løsning

Update transaction som tjekker om data er blevet ændret siden SELECT-udtrækket.

Hej udviklere.

Jeg er ikke den skarpeste MSSQL (jeg benytter i dette tilfælde MSSQL2005) / SQL-person og har oftest kun brugt banale UPDATEs, INSERTS, SELECTs, etc.

Men nu skal jeg vidst bruge noget mere transaktions-orienteret.

Har en database med nogle simple oplysninger (Navn, adresse, telefonnummer, etc.) og disse bliver så trukket ud og fyldt i nogle tekstfelter så den enkelte bruger kan redigere dem.

Hver af applikationerne (winforms) snakker direkte med en database og derfor vil jeg gerne have at når der trykkes "Gem oplysninger", så skal den "låse" det database-record og tjekke om nogle er oplysningerne er ændret (og i såfald hvilke) og hvis de er så skal brugeren have mulighed for "overwrite", "cancel" eller "Get updated data" og hvis de ikke er skal den bare UPDATE.

Er i tvivl om hvordan dette skal gøres og der er garanteret også nemmere måder (og måske indbyggede metoder) som jeg ikke kender til.

Vil det give mening at:
BEGIN TRANSACTION
SELECT (samme record igen)
UPDATE (record med nye oplysninger)
Tjek rent kodemæssigt (benytter C#) om der var ændringer fra det første udtræk til det andet.
Hvis det var ændringer, så Rollback.
Hvis der ikke var ændringer, så Commit.


Giver dette mening eller er jeg helt off?

Hilsen Kasper.
Avatar billede teepee Nybegynder
07. maj 2010 - 12:48 #1
En let måde at styre det på er at man gemmer created_by og modified_by på tabellerne, og vedligeholder dem via en IU-trigger.
Når du selecter din række ud til update husker du det sidst ændret tidspunkt i modified_by.
Når du sender din update afsted kan du skrive
update tabelnavn where primærnøgle = dinrækkeid AND modified_by=dengamle_modified_by.
Hvis den opdaterer nul rækker så er rækken ændret siden sidst.
Alternativt kan du også skrive samtlige kolonners gamle værdier i din where-clause når du laver en update. 0 rækker, så er den ændret.
Avatar billede thepsypher Nybegynder
07. maj 2010 - 13:56 #2
Havde ikke rigtig overvejet den forholdsvis simple/logiske udgave, hvor jeg bare sammenligner med alle de gamle værdier i WHERE-klausulen. Tror jeg benytter mig af denne. Den giver vidst også en fordel i forhold til den først-nævnte løsning, nemlig at hvis folk updater med de samme data som allerede lå der, så vil modified_by jo være ændret, men ingen celler vil réelt være ændret. Så kan den jo poppe følgende op i GUIen:

"Brugeroplysningerne er blevet ændret siden sidst.
Følgende er ændret: null", da jeg vil liste de celler som er blevet ændret. På den anden måde er det réelt kun hvis der er ændringer og så kan den vise dem:

"Brugeroplysningerne er blevet ændret siden sidst.
Følgende er ændret:
Navn er skiftet fra 'Bjarne' til 'Torkild'.
Adresse skiftet fra 'Mosebuen 12' til 'Travervænget 11a'.". Jeg kan selvfølgelig kode mig ud af det, men syntes vidst at det giver et bedre kode-flow.

Men vil løsningen så være:

UPDATE Personer WHERE (alle data=alle gamle data)
IF rowsaffected=0 then (træk samme person ud igen fra ID)
Sammenlign ny-udtrukne data og gamle data.
Vis en messagebox med alle uoverensstemmelserne/ændringerne.
Avatar billede thepsypher Nybegynder
07. maj 2010 - 14:15 #3
Nu bliver jeg helt forvirret over mine egne tanker! :-S

På min sidst-nævnte måde kan en anden bruger jo nå at ændre data fra messageboxen med ændringerne vises til man vælger at overskrive data eller hente ændringerne ind.

Så kan man jo overskrive data på et forkert grundlag... :-/
Avatar billede Syska Mester
07. maj 2010 - 14:38 #4
Ja, ved sidste ide, skal du stadig have en timestamp ... det vil løse den del.

mvh
Avatar billede arne_v Ekspert
07. maj 2010 - 15:32 #5
Du kan vaelge mellem optimistic og pessimistic locking.

http://www.eksperten.dk/guide/996 gaa ned til "long time locking" for en meget kort gennemgang
Avatar billede janus_007 Nybegynder
07. maj 2010 - 21:03 #6
Du skal vælge løsningen som buzzz foreslår, nemlig med timestamp. Sådan en bruges nemlig til... og det som du skal søge efter hedder 'optimistic concurrency'.

Timestamp skifter forøvrigt til rowversion :)
Avatar billede janus_007 Nybegynder
07. maj 2010 - 21:06 #7
ovvv.... lige for at slå en ting på plads... Timestamp har intet med datetime at gøre :), glem modified_date eller hvad der ellers blev foreslået.

Brug timestamp/ rowversion det er er forøvrigt også understøttet direkte i ADO.NET eller Linq og du behøver ikke selv sidde og kode noget knald.
Avatar billede thepsypher Nybegynder
07. maj 2010 - 22:47 #8
Det lyder som nogle fornuftige kommentarer. Må lige gå in-depth med det i week-enden. Tak indtil videre! :-)
Avatar billede janus_007 Nybegynder
09. maj 2010 - 19:54 #9
.
Avatar billede thepsypher Nybegynder
11. maj 2010 - 12:43 #10
Er umiddelbart desværre forced til at benytte timestamp, da det er op imod MS SQL server 2005...

SELECT en person fra Personer og husk timestamp.

(Bruger bliver præsenteret for data og redigerer i den over tid)
    (Lykke1)
    rowsaffected = UPDATE Personer WHERE (ID=id og
    timestamp=det-huskede-timestamp)
    IF rowsaffected=0 then (træk samme person ud igen fra ID og
    husk igen hans timestamp)
    Sammenlign ny-udtrukne data og gamle data.
    Vis en messagebox med alle uoverensstemmelserne /
    ændringerne og afvent enten "overskriv" eller "cancel".
    Hvis "cancel" så abort.
    Hvis "overskriv", så gentag lykke1
    (\Lykke1)


Ville dette mon give mening (hvis folk altså kan finde hoved og hale i mit abstrakte pseudo-kode! )?


Tanken er så at den bliver ved med at præsentere ændringerne til brugeren indtil der ikke længere er blevet lavet ændringer i mellemtiden og så går den igennem og opdaterer korrekt.

På den måde vil man så ikke kunne tage stilling på forkert baggrund, men vil derimod blive ved med at få at vide at data er blevet ændret indtil dette ikke længere er tilfældet.

Nogle kommentarer folkens? :-)

Hilsen Kasper.
Avatar billede arne_v Ekspert
12. maj 2010 - 02:03 #11
Det er vel ca. sådan man gør 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
Computerworld tilbyder specialiserede kurser i database-management

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