![]() |
Datenbank: Firebird • Version: 1.5 • Zugriff über: IBX / UIB
Wie kann man mit tiOPF Generatoren nutzen
Hallo zusammen,
ich arbeite mich gerade in die Nutzung des tiOPF-Frameworks ein. Soweit habe ich das auch alles installiert und alle Demo's zum Laufen bekommen. Da google hierzu auch nicht sonderlich hilfreich ist, möchte ich meine Frage mal bei Euch loswerden - in der Hoffnung es nutzt noch jemand tiOPF. Es gibt in der Firebird-Datenbank (V1.5) sehr viele Tabellen, welche die ihren Primärschlüssel ID haben. Dieser wird in der bestehenden Anwendung durch Zuweisung von "GEN_ID(GEN_NAME, 1) FROM RDB$DATABASE" gefüllt. Jetzt versuche ich diese Logik auf tiOPF umzusetzen, finde aber bisher keinen geeigneten Weg dazu. Mein erster Schritt war dabei die Anlage eines Hard-Coded-Visistors um das ID-Feld auf die interne OID abzubilden. Laden, Selektieren, Editieren, Speichern und Löschen funktioniert auch einwandfrei. Nur beim Einfügen von neuen Datensätzen finde ich keinen Ansatz nach dem Speichern eines neuen Datensatz dessen generierte (Trigger/Generator) ID herauszufinden. Die angegebene SQL-Anweisung für den Create-Visitor funktioniert auch, allerdings komme ich nicht an die erzeugte ID heran. Die bräuchte ich aber in der Folge, damit tiOPF seinen Datensatz wiedererkennen kann. Neu laden aller Datensätze wäre ein Ansatz, kostet aber bei vielen Datensätzen Performance ohne Ende. Oder das Neu-Lesen mit Maximum(ID), wobei andere User mittlerweile auch Datensätze angelegt haben könnten. Also auch keine gute Idee. Hat jemand von Euch damit schon Erfahrungen gemacht oder eine Tipp dazu? Gruss Carsten
Delphi-Quellcode:
{ TVisName_Create }
function TVisName_Create.AcceptVisitor: boolean; begin result := (Visited is TPName) and (Visited.ObjectState = posCreate); Log([ClassName, Visited.ClassName, Visited.ObjectStateAsString, Result]); end; procedure TVisName_Create.Init; begin Query.SQLText := 'INSERT INTO TEST (NACHNAME, VORNAME) VALUES (:NACHNAME, :VORNAME)'; end; procedure TVisName_Create.SetupParams; var lData: TPName; begin lData := Visited as TPName; // OID braucht nicht gefüllt werden, das erledigt der Trigger automatisch Query.ParamAsString['Nachname'] := lData.Nachname; Query.ParamAsString['Vorname'] := lData.Vorname; end; |
Re: Wie kann man mit tiOPF Generatoren nutzen
Auch wenn der Trigger die ID automatisch vergeben kann, ist es in diesem Fall besser die ID vor dem Insert zu erzeugen.
Ein denkbarer Weg wäre, wäre bei der Datenklasse ein eigener "constructor CreateNew()" dem der Generatorname mit übergeben wird und eine eigene Generatorklasse beim GTIOPFManager registrieren, die mit diesem Parameter etwas anfangen kann. |
Re: Wie kann man mit tiOPF Generatoren nutzen
Gute Anregung - habe mir jetzt eine Generatorklasse geschrieben, welche den Wert aktuell beim Belegen des Objektes in CreateNew bestimmt. Das ist momentan noch sehr rudimentär ohne ttiObjectList drumherum, mit der ich sicherlich die ganzen benötigten Generatoren in einer Art Collection halten könnte.
Aber zum weiteren testen bezüglich Umstellungsaufwand funktioniert es jetzt erstmal mit kurzzeitigem Erzeugen des Generator-Objektes und belegen der OID mit dem Generatorwert. Danke nochmal für den Tipp, hast Du da ggf. schon etwas ausgefeilteres gebaut? Carsten und vielleicht kann es nochmal jemand brauchen, deshalb hier mein Denkansatz
Delphi-Quellcode:
// Grundklasse
uses Classes ,SysUtils ,Windows ,tiObject ,Generator_HCV ,Generator_BOM ; .... // Beispielaufruf in CreateNew des eigentlichen Tabellenobjektes constructor TPName.CreateNew(const ADatabaseName, APersistenceLayerName: string); var lGen: TPGenerator; begin inherited Create; // Get an ID from Generator lGen := TPGenerator.Create; lGen.GeneratorName := 'GEN_TEST_ID'; lGen.ObjectState := posCreate; lGen.Read; // Stösst Read in Generator_HCV an und belegt OID aus dem Generator OID.AsVariant := lGen.OID.AsVariant; lGen.Free; end; // Quelltext Generator_BOM.pas unit Generator_BOM; interface uses Classes ,SysUtils ,Windows ,tiObject ; const cErrorGeneratorNameMissing = 'Kein GeneratorName bekannt!'; type TPGenerator = class(TtiObject) private FGeneratorName: string; protected public function IsValid(const AErrors: TtiObjectErrors): boolean; override; procedure Read; overload; published property GeneratorName: string read FGeneratorName write FGeneratorName; end; implementation uses tiOPFManager , tiOIDInteger ; { TPGenerator } function TPGenerator.IsValid(const AErrors: TtiObjectErrors): boolean; begin inherited IsValid(AErrors); if Trim(GeneratorName) = '' then AErrors.AddError('GeneratorName', cErrorGeneratorNameMissing); result := AErrors.Count = 0; end; procedure TPGenerator.Read; begin inherited Read; end; end. // Quelltext Generator_HCV.pas unit Generator_HCV; interface uses tiVisitorDB ; type TVisGenerator_Read = class(TVisOwnedQrySelect) protected function AcceptVisitor: boolean; override; procedure Init; override; procedure SetupParams; override; procedure MapRowToObject; override; end; procedure RegisterVisitors; implementation uses Generator_BOM , tiOPFManager , tiObject , tiLog , tiCriteria , tiVisitorCriteria ; procedure RegisterVisitors; begin GTIOPFManager.RegReadVisitor(TVisGenerator_Read); end; { TVisClient_Read } procedure TVisGenerator_Read.MapRowToObject; var lGenerator: TPGenerator; begin lGenerator := TPGenerator(Visited); lGenerator.OID.AsVariant := Query.FieldAsIntegerByIndex[0]; lGenerator.ObjectState := posClean; end; function TVisGenerator_Read.AcceptVisitor: boolean; begin result := (Visited is TPGenerator) and (Visited.ObjectState = posCreate); Log([ClassName, Visited.ClassName, Visited.ObjectStateAsString, Result]); end; procedure TVisGenerator_Read.Init; var lData: TPGenerator; begin lData := TPGenerator(Visited); Query.SQLText := 'SELECT GEN_ID(' + lData.GeneratorName + ',1) FROM RDB$DATABASE'; end; procedure TVisGenerator_Read.SetupParams; begin ; end; end. |
Re: Wie kann man mit tiOPF Generatoren nutzen
auch ein netter Weg ist (allerdings nur bei Firebird ab 2.1 glaube ich):
SQL-Code:
vielleicht muß man dann noch einen Parameter erzeugen, hängt von den verwendeten Komponenten ab - achja und einen Trigger brauchst du, der ID mit NULL automatisch generiert...
insert into Table (ID, ...) values (null, ...) returning ID
Delphi-Quellcode:
Also zumindest mit den Komponenten, die wir bei uns einsetzen, geht das...
var
p: TParam; begin qry.SQL.Text := '... returning ID'; p := TParam.Create; p.ParamType := ptOutput; p.DataType := ftInteger; qry.Params.Add(p); qry.Execute; ID := qry.ParamByName('ID').AsInteger; end; |
Re: Wie kann man mit tiOPF Generatoren nutzen
Zitat:
Geht tatsächlich erst ab 2.x, da wir hauptsächlich 1.5 Datenbanken installiert haben, fällt das momentan aus. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz