04. august 2007 - 13:07Der er
5 kommentarer og 1 løsning
Indsætte grafstruktur - hvordan findes id'er
Hej
Jeg er igang med et projekt hvor jeg skal lave en database der indeholder records over nogle hændelser i et kundeservice system. Disse hændelser er organiseret i en grafstruktur (noget der minder meget om en træstruktur på hovedet). Hver hændelse har således 2 parents (pånær "root hændelser") og mulighed for 1 child.
Min opgave er at hente database records for de her hændelser fra en række databaser (identiske i struktur, men forskellig) data, og så samle dem i en database og lave lidt kalkulering af værdier til noget OLAP agtigt analyse. Problemet er hvordan jeg får givet dem en id, så at de forskellige records kan referere til hinandens id. Jeg kan ikke genbruge de id's de har i de enkelte databaser (da de ikke er unikke på tværs af source databaserne).
Problemet er således lidt simplificeret, at jeg skal indsætte A som skal referere B i et child felt, og derefter indsætte B som skal pege på A i et parent felt. jeg kan derfor ikke se hvordan jeg fx kan bruge en autogenereret id, da jeg jo så ikke kender den på det tidspunkt hvor den skal bruges.
Er løsningen at smække alle nodesne ind, se hvilken id de får, og så opdatere hele baljen, eller findes der en smartere løsning til det her?
Jeg kan sagtens behandle dataen inden, så er selvfølgeligt en mulighed at lade min applikation generere unikke id'er og tildele til dem. Import processen er altid "serialiseret", så man kunne måske gemme en "new_id_counter" et andet sted i databasen, og så fortsætte fra den hver gang import koden kører.
Har det fået til at virke med fra applikationen at tildele en unik id til hver record, og så i en "property" tabel at gemme hvor langt jeg kom efter hver import run. Smider du et svar? Vil i øvrigt gerne høre fra folk hvis der er nogle best-practice/smarte måder at holde styr på den her applikations id på.
Jeg kan godt smide et svar (hermed gjort). Lige et spørgsmål til det sidste du nævner, at A peger på B, men at B også peger tilbage på A. Er det nødvendigt at B kender A?
Det er ikke det store problem hvis du har hele din grafstruktur i hukommelsen á la (kodeeksempel i Delphi):
procedure TData.WriteRecord(aQuery : TADOQuery); begin aQuery.SQL.Text := 'insert into data'+ ' (ID, Parent1ID, Parent2ID, ChildID)'+ ' values (:ID, :Parent1ID, :Parent2ID, :ChildID)'; aQuery.Parameters.ParamByName('ID').Value := fUniqueID; with aQuery.Parameters.ParamByName('Parent1ID') do if assigned(fParentID1) then Value := fParentID1.UniqueID else Value := NULL; with aQuery.Parameters.ParamByName('Parent2ID') do if assigned(fParentID2) then Value := fParentID2.UniqueID else Value := NULL; with aQuery.Parameters.ParamByName('ChildID') do if assigned(fChildID) then Value := fChildID.UniqueID else Value := NULL; aQuery.ExecSQL; end;
.. Indlæsningen må ske i en overordnet klasse der kan administrere træet og foretage søgninger i det (en eller anden objektliste-klasse):
TDataContainer.ReadData; var Query : TADOQuery; Data : TData; Parent1, Parent2, Child : TData; begin Query := TADOQuery.Create(nil); try ... Query.SQL.Text := 'select ID, Parent1ID, Parent2ID, ChildID from data'; Query.Open; while not Query.Eof do begin Data := TData.Create(Query.FieldByName('ID').Value, Query.FieldByName('Parent1ID').Value, Query.FieldByName('Parent2ID').Value, Query.FieldByName('ChildID').Value);
Add(Data); // Føj til contailer
Parent1 := Lookup(Data.Parent1ID); if assigned(Parent1) then begin Parent1.ChildID := Data; Data.Parent1 := Parent1; end;
Parent2 := Lookup(Data.Parent2ID); if assigned(Parent2) then begin Parent2.ChildID := Data; Data.Parent2 := Parent2; end;
Child := Lookup(Data.ChildID); if assigned(Child) then begin if assigned(Child.Parent1) then Child.Parent2 := Data else Child.Parent1 := Data; Data.Child := Child; end; Query.Next; end; finally Query.Free; end; end;
TDataContainer.WriteData; var i : integer; Data : TData; Query : TADOQuery; begin // Begin work try for i := 0 to Count - 1 do begin Data := Items[i] as TData; Data.WriteRecord(Query); end; // Commit work except // Rollback work end; end;
Indlæsningen vil blive lidt tung, men ikke noget der skulle kunne mærkes (medmindre det bliver kodet i VB (!)). Så fik du lige mit bud.
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.