Toon posts:

[Delphi] Eigengemaakt DB component bij starten active, hoe?

Pagina: 1
Acties:

Verwijderd

Topicstarter
De titel is een beetje cryptisch, maar soit.

Ik heb een eigengemaakt database component, welke als properties 'database' en 'transaction' heeft (resp TIBDatabase en TIBTransaction).

Deze heeft ook een property 'active'. Zodra deze naar true gezet wordt, controleert hij of de database en transaction assigned zijn en of de database verbinding heeft. Zo ja, dan haalt hij z'n dataset op om weer te geven.

Dit werkt allemaal prima zodra ik designtime of runtime active van 'false' naar 'true' zet, doet hij het perfect.

Het enige wat hij niet goed doet.. als ik 'm designtime op active laat staan, en dan de applicatie run, is er geen dataset. Zelfde geldt als ik 'm designtime op active laat staan en dan opsla, sluit en weer laad.

Hoewel dit niet echt cruciaal is, wil ik dit toch goed hebben. Als ik 'm designtime active laat staan, moet hij ook bij runnen de data laten zien, of bij opnieuw laden.

Met een beetje steppen kwam er achter dat in eerste instantie de property 'active' geladen werd voordat hij de property 'database' en 'transaction' geladen had. Dit heb ik opgelost door de Twincontrol.loaded te overriden, en 'm daar te laten kijken wat z'n status is. Indien active --> weergeven dataset.

Dit werkt echter niet. Het blijkt dat op het moment dat hij die loaded krijgt, de database nog niet connected is. Als het form helemaal klaar is met laden, is hij dat uiteraard wel.

Hoe krijg ik dit nu voor elkaar? De volgende twee zaken zijn geen opties:

1) form.loaded, form.onshow, enzovoort. Het moet in de class zelf geregeld worden
2) database.onlogin, database.onconnect, etc. éen database kan meerdere componenten aan zich hebben hangen

Kort.. delphi laadt eerst mijn component helemaal in (bij runnen of bij inladen in IDE) en zet dan pas de database naar connected. Hoe draai ik dit om?

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Weet je zeker dat het niet gewoon een probleem is met de default value van je Active property? Kan je bij jouw Active property er niet gewoon voor zorgen dat de database ook op Active wordt gezet. Kijk eens in de code van het database component. Wanneer wordt ie dan actief?

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
LordLarry schreef op maandag 20 december 2004 @ 09:25:
Weet je zeker dat het niet gewoon een probleem is met de default value van je Active property?
Ja; die heeft nl. geen default value :)
Kan je bij jouw Active property er niet gewoon voor zorgen dat de database ook op Active wordt gezet.
Dat gaat helaas niet, omdat hij de parameters van de database op dat moment nog niet geladen heeft.

[code]
Kijk eens in de code van het database component. Wanneer wordt ie dan actief?[/quote]

Het database component heb ik dus zelf gemaakt. De database wordt pas geladen, nadat mijn component helemaal geladen is.

In de delphi databasecomponenten lossen ze dit op door er een component tussen te plakken (de datasource) die een lijst bijhoudt. Ik zou het echter liever zonder apart component doen.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Als het je eigen component is kan je toch wel een event maken om te melden dat ie er klaar voor is? Ik begrijp dat je meerdere componenten aan dezelfde database wilt koppelen dus een gewoon event zal niet voldoen. Je zou een een observer pattern kunnen implementeren waarbij men zich kan registreren op een event.

PS: TIBDatabase is toch al een bestaand component?

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
LordLarry schreef op maandag 20 december 2004 @ 10:56:
Als het je eigen component is kan je toch wel een event maken om te melden dat ie er klaar voor is? Ik begrijp dat je meerdere componenten aan dezelfde database wilt koppelen dus een gewoon event zal niet voldoen. Je zou een een observer pattern kunnen implementeren waarbij men zich kan registreren op een event.

PS: TIBDatabase is toch al een bestaand component?
TIBDatabase wel ja :P

Observer pattern is dus de oplossing met een datasource oid ertussen, en dat wilde ik niet.. maar goed, er lijkt geen ontkomen aan, dus zal wel moeten :P

Ik zal proberen duidelijker uit te leggen wat ik bedoel. De volgende code is niet echt, dus er kunnen fouten in zitten en het is zeker niet elegant, maar het gaat even om het systeem:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
type 
  TmijnCompo = class(TWinControl)
       Factive: Boolean;
       FDatabase: TIBDatabase;
       FTransaction: TIBTransaction;
       FQuery: TIBQuery;
    private
       procedure SetActive(Value: Boolean)
    published
      property Active: Read FActive write SetActive;
      property Database: TIBdatabase read FDatabase write FDatabase;
      property Transaction: TIBTransaction read FTransaction write FTransaction;
  end;

[..]

procedure TmijnCompo.SetActive(Value: Boolean);
  begin
     If FActive<>Value then
        begin
            FActive:=Value;    
            If not Assigned(TIBDatabase) then Factive:=False;
            If not Assigned(TIBTransaction) then Factive:=False;
            If Assigned(TIBDatabase) then 
              If not TIBDatabase.Connected then Factive:=False;
            If FActive then
               begin
                    FQuery:=TIBQuery.Create(self)
                    try
                      FQuery.Database:=FDatabase;
                      FQuery.Transaction:=FTransaction;
                      FQuery.SQL.Add('wat sql meuk');
                      FQuery.Open;
                      ShowMessagE(FQuery.FieldByName('eenveld').AsString);
                      FQuery.Close;
                    finally
                      FQuery.Free;
                    end;
               end;
        end;
  end;


Stel nu ik pleur dit component op een form, koppel 'm aan een (connected) database en een transaction. Daarna zet ik 'm in de object inspector op 'active'. Hij zal dan netjes de showmessage doen.

Nu laat ik alles zo staan, save het project en sluit Delphi. Ik open weer Delphi en open het project.

Nu zou je verwachten dat hij bij het openen van dat project de showmessage uitvoert. Echter, dit doet hij niet omdat op het moment dat hij de property Active toekent (dus terugzet naar true), is de connected property van de TIBDatabase nog niet true.

Dat was zeg maar poging één. Dan poging twee:


Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
type 
  TmijnCompo = class(TWinControl)
       Factive: Boolean;
       FDatabase: TIBDatabase;
       FTransaction: TIBTransaction;
       FQuery: TIBQuery;
    private
       procedure SetActive(Value: Boolean)
    protected
       procedure Loaded;override;
    published
      property Active: Read FActive write SetActive;
      property Database: TIBdatabase read FDatabase write FDatabase;
      property Transaction: TIBTransaction read FTransaction write FTransaction;
  end;

[..]

procedure TmijnCompo.SetActive(Value: Boolean);
  begin
    If not (csLoading in Componentstate) then
      begin     
        If FActive<>Value then
            begin
                FActive:=Value;    
                If not Assigned(TIBDatabase) then Factive:=False;
                If not Assigned(TIBTransaction) then Factive:=False;
                If Assigned(TIBDatabase) then 
                If not TIBDatabase.Connected then Factive:=False;
                If FActive then
                   begin
                        FQuery:=TIBQuery.Create(self)
                        try
                          FQuery.Database:=FDatabase;
                          FQuery.Transaction:=FTransaction;
                          FQuery.SQL.Add('wat sql meuk');
                          FQuery.Open;
                          ShowMessagE(FQuery.FieldByName('eenveld').AsString);
                          FQuery.Close;
                        finally
                          FQuery.Free;
                        end;
                   end;
        end
      else
         Factive:=Value;
  end;
[..]
procedure TMijnCompo.Loaded
begin
  inherited;
  If Active then 
    begin
       FActive:=False;
       Active:=True;
    end;
  
end;


... nou ja, niet allemaal zo smerig, maar het idee is duidelijk denk ik. Dit werkt dus ook niet omdat ook na een loaded, die verrekte database nog steeds op niet connected staat.

Ik vrees idd dat het niet gaat werken anders dan met een class ertussen die observed..

[ Voor 96% gewijzigd door Verwijderd op 20-12-2004 11:18 ]


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Kan je anders niet kijken hoe TADOConnection/TADOTable of TDatabase/TTable het doen?

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
Door een tussenliggende class waarbij de datacomponenten zich registreren. Dat lijkt dus de enige manier om dit te doen.

Een andere manier die wel werkt, is het component een timer mee te geven die na een halve seconde alsnog de zaak verbind (database is dan wel verbonden), maar die oplossing vind ik te smerig. Wordt dus toch een observer maken.

Verwijderd

Topicstarter
Ik heb het inmiddels opgelost door er een eigen datasource-achtig component bij te zetten.

Dit component zet in de Afterconnect en Afterdisconnect een event, en bij aanroepen van dit event meldt hij alle aangemelde clients dat de database connected/disconnected is. Indien de connection property van een client gezet wordt, meldt de client zich aan. Zodra een client gedestroyed wordt, meldt ie zich weer af.

Werkt als een tiet.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Tussen een TADOConnection en een TADOTable zit geen TDataSource en toch werkt het daar met zo'n Active property.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
LordLarry schreef op woensdag 22 december 2004 @ 09:05:
Tussen een TADOConnection en een TADOTable zit geen TDataSource en toch werkt het daar met zo'n Active property.
Inderdaad.. ik heb het even bekeken, en die doen het zo:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TCustomADODataSet.SetConnection(const Value: TADOConnection);
begin
[..]
if Connection <> Value then
  begin
     [..]
      Value.RegisterClient(Self);
     [..]
  end;

[..]
procedure TADOConnection.RegisterClient(Client: TObject; Event: TConnectChangeEvent = nil);
begin
  [..]
    FCommands.Add(Client);
end;


De TADOConnection heeft dus zelf al een observator. De IBDatabase of IBTransaction hebben dat helaas niet, dus moet ik die er zelf tussen zetten.

Toch ben ik blij dat ik even gekeken heb (bedankt voor de tip) ik zie namelijk dat zij het op exact dezelfde manier gedaan hebben als ik; dat is toch prettig; dan weet je dat je op de juiste weg zit. Zelfs de functie/procedure namen zijn gelijk :P

[ Voor 6% gewijzigd door Verwijderd op 22-12-2004 20:47 ]

Pagina: 1