29. juli 2008 - 23:48Der er
9 kommentarer og 2 løsninger
Exception handler
Hej.
Jeg skal til at skrive en exception handler, hvilket er et nyt emne indenfor programmering for mig.
Min første exception handler skal bruges i forbindelse med en DBGrid og en Clientdataset, som er forbundet sammen. Clientdataset'et er ligeledes forbundet med en database, hvor feltet KONTO er primær nøgle.
Når en ny record postes i DBGrid'en / clientdataset'et får man en exception, hvis feltet KONTO ikke er udfyldt. Som standard er det en EDatabaseError med beskeden Field ’Konto’ must have a value. Den skal jeg have lavet "dansk"
Det som jeg vil gøre er, at jeg i clientdataset'ets BeforePost event skriver:
try clientdataset1.post; except on E : EDatabaseError do showMessage('Feltet 'konto' skal udfyldes'); end
Dette efterlader nogle spørgsmål.
1. Er der en fejl? De medfører hos mig en fejl. Ikke en compilerfejl, men runtime, når jeg forsøger at indsætte en ny linie i min grid, skriver en tekst i et felt, men lader feltet konto være tomt for derefter at vælge en anden linie, så linien bliver postet. Jeg får en stack overflow error, hvis programmet køres fra Delphi og køres programmet via exe-filen lukker den uden yderligere info eller fejlbeskeder.
2. Er det rigtigt at placere exception handleren i BeforePost eventen?
3. Kan man ikke specificere eventhandleren mere præcist? En EDatabaseError kan jo være mange ting og er ikke ensbetydende med, at det skal være den samme fejlbesked, som brugeren skal have. Eksempelvis kan det jo være andre databasefejl end lige, at det er feltet Konto, der mangler at blive udfyldt.
1+2) Jeg vil tro at idet du i din event handler kalder Post på dit dataset, bliver BeforePost kaldt (igen) - fordi den jo skal udføres INDEN post'en (hvilket også vil sige at posten allerede er i gang når du er nået til din Post-linje). Derfor får du en stack overflow - og programmet lukker ned fordi den ikke kan nå at reagere på det. Du bør derfor flytte det kode ud til der hvor du nu sætter din post igang (nu har jeg aldrig arbejdet med DBGrid og ClientDataSet, så der er du lidt på egen hånd).
3) Nej, du kan kun angive typen på den exception du vil fange - selvfølgelig kan du angive en anden type, men det skal jo være en der bliver returneret (måske er der en EDatasetFieldNotSet eller noget). Det kan du kombinere med at kigge på hvad der ligger i dit exception-objekt - igen, har ikke arbejdet med dem, og kender ikke dit direkte behov til fejlmeddelelsen, så kan ikke gøre andet end at pege dig i retningen af dens Message.
I BeforePost skal du validere data, "raise exceptions" og "abort post"
procedure ... (DataSet: TDataSet); begin try with DataSet.FieldByName('konto') do if IsNull or (Value = 0) then raise Exception.Create('Feltet konto skal udfyldes');
except on e: exception do begin ShowMessage(e.Message); abort; end; end; end;
Du har ikke brug for at vente på EDatabaseErrors - medmindre du vil validere på DupKeys, altså hvis det kan se at man indsætter record med samme primærnøgle - hvilket kan ske i flerbrugermiljøer.
En EDatabaseError er i øvrigt direkte nedarvet fra Exception så der kan du ikke finde oplysninger. Nogle gange er EDatabaseError dog nedarvet til også at indeholde en errorcode som fortæller hvad der er gået galt:
procedure TfrmKontoplan.cdsKontoplanBeforePost(DataSet: TDataSet); begin try with DataSet.FieldByName('Konto') do if IsNull or (Value = 0) then raise Exception.Create('Feltet konto skal udfyldes'); except on E : Exception do begin abort; showmessage(e.Message); end; end; end;
Men den medfører, at hvis fletet konto IKKE er indtastet, så kan jeg hverken poste, få fejlbesked, lukke eller noget. Ved ikke, om det er 'abort' der gør, at den "ikke gør noget"
Skal jeg have byttet rundt på noget eller mangler jeg noget?
Aborten er en usynlig exception der afbryder post-operationen. Din record kommer aldrig ud af dsInsert/dsEdit tilstanden så datasættet må du give et "Cancel" hvis du vil lukke uden at gemme.
I en form kan du eventuelt tage den operation i OnCloseQuery:
if Table1.State in [dsEdit,dsInsert] then if ModalResult = mrOK then Table1.Post else Table1.Cancel;
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.