Avatar billede skindbeni Nybegynder
08. juli 2009 - 11:01 Der er 7 kommentarer og
1 løsning

Problemer med at autogenerere et felt

Jeg har en Delphi 2007 applikation.

Jeg har en IBQuery, Datasetprovider, ClientDataSet og en Datasource forbundet i nævnte rækkefølge og en Grid som er forbundet til datasourcen.

IBQuerien er forbundet med en Firebird 2,1 database.

Tabellen er her i simpel udgave

ID, pk, integer
Navn, varchar(50)
Beskrivelse, varhcar(250)

Feltet ID ønskes skjult i min grid og feltet skal autogenereres med en værdi på serveren.

Derfor har jeg lavet en generator (sequense) i min Firebird database:

CREATE SEQUENCE GEN_KASSEKLADDER_ID;
ALTER SEQUENCE GEN_KASSEKLADDER_ID RESTART WITH 0;

Jeg har også forsøgt med en trigger:

CREATE OR ALTER TRIGGER KASSEKLADDER_BI FOR KASSEKLADDER
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF ((NEW.KLADDEID IS NULL) or (New.KladdeID = 0)) THEN
    NEW.KLADDEID = GEN_ID(GEN_KASSEKLADDER_ID,1);
END


Problemet er, at når jeg kører min application, så får jeg en fejl "Field ID must have a value"

Fejlen kommer ikke når en ny post indsættes i min clientdataset, men først når jeg forsøger at forlade den nye post igen enten ved at flytte til posten ovenover eller lukke formen osv.
Avatar billede hrc Mester
16. juli 2009 - 00:14 #1
Løsningen jeg (vi) bruger er, at have en generator for hver tabel og tælles op hver gang man, via en SProc, spørger. SProc'en er skrevet specifikt til tabellen.

Alternativet er at have en tabel (tabelnavn, id) til alle tabellernes ID'er. Har brugt begge løsninger og ved ikke hvad der er hurtigst. Her tager SProc'en tabelnavnet som parameter.

ID'et sætter jeg via programmet i tabellens/queryens OnNewRecord eller i OnBeforePost.

(Triggeren har jeg aldrig fået til at virke.)

Poster en løsning om et øjeblik (skal på med VPN)
Avatar billede hrc Mester
16. juli 2009 - 00:29 #2
SProc'en ser sådan ud:

  BEGIN REF = GEN_ID(<generator>, 1); END

Funktionen har jeg lavet således (bruger InfoPower men det ligger nok tæt op ad hvad du bruger):

function TDM.GetId(const aTableName: string): longint;
begin
  wwStoredProc.StoredProcName := format('SET_%s_ID',[AnsiUpperCase(aTableName)]);
  wwStoredProc.ExecProc;
  result := wwStoredProc.Params[0].AsInteger;
end;

Kender du i øvrigt IBOConsole? Den er eminent til at kigge i Firebird/Interbase tabeller
Avatar billede skindbeni Nybegynder
21. juli 2009 - 00:05 #3
Hej hrc.

Mange tak for dit svar.

Jeg har en ferie, der går med at planlægge og afholde et bryllup på lørdag, så jeg når ikke at kigge på din løsning før næste uge, måske ugen efter.

Jeg skal selvfølgelig nok vende tilbage med respons og points.

/Michael
Avatar billede hrc Mester
21. juli 2009 - 08:03 #4
Antager jeg skal ønske tillykke (det kan jo også være en andens bryllup) - tænk det får lov til at forstyrre programmeringen.
Avatar billede skindbeni Nybegynder
01. august 2009 - 01:45 #5
Hej hrc.

Ja så endte det jo med, at jeg blev gift. Nu har konen været spændende i et par dage, men nu er det igen programmeringen, der trækker :o)

Dette er mit første møde med en sproc.

Jeg kan dels ikke gennemskue din funktion (det er nok mest første linie). Samtidig har jeg også kvaler med sproc'en. Hvad er "REF" lige for en størrelse.

Jeg benytter forresten Delphi 2007 og de tilhørende Interbase Express komponenter. Eneste købekomponenter jeg anvender er fra DevExpress. Bruger desuden IB Expert til at opbygge og vedligeholde min Firebird databaser.
Avatar billede hrc Mester
01. august 2009 - 11:48 #6
2 dage er eller også et stykke tid. Hun er sikkert lykkelig over den opmærksomhed. Tillykke.

På arbejdet bruger vi REF (for reference = primærnøgler). På eksperten valgte jeg engang at det skulle hedde ID - og så må jeg jo omdøbe ref til ID hver gang jeg kopierer eksempler fra arbejdet.

SProc'en ser sådan ud (hvor <generator> erstattes med navnet på generatoren):

BEGIN ID = GEN_ID(<generator>, 1); END


Funktionen har jeg lavet således (bruger InfoPower men det ligger nok tæt op ad hvad du bruger):

function TDM.GetId(const aTableName: string): longint;
begin
  wwStoredProc.StoredProcName := format('SET_%s_ID',[AnsiUpperCase(aTableName)]);
  wwStoredProc.ExecProc;
  result := wwStoredProc.Params[0].AsInteger; // ID eller REF
end;
Avatar billede hrc Mester
01. august 2009 - 11:57 #7
Procedure ser vistnok sådan her ud:

CREATE PROCEDURE SET_<TABLE>() RETURNS (ID INT)
AS
BEGIN
  ID = GEN_ID(<generator>, 1);
  SUSPEND;
END

Vi bruger ikke SUSPEND men det ser ud til at være en god idé (i alt fald med Interbase):

http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_intro_sp_trig
Avatar billede skindbeni Nybegynder
08. august 2009 - 23:45 #8
Hej hrc.

Så fik jeg løst problemet. Det tog sin tid, men først bryllup og i denne uge startet i andet revisionsfirma, så tiden har ikke været der. Men hovedsagen er vel, at det virker nu.

Jeg har nu sendt points afsted til dig.
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
Kurser inden for grundlæggende programmering

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