[Delphi] DCOM server childs

Pagina: 1
Acties:

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik heb een DCOM server met een GeneralModule (RDM), verder heeft de server een stuk of 4 childs. Werkt allemaal zeer goed, alleen nou moeten de childs beschikking hebben over de ADOConnection die in de GeneralModule zit. Hoe krijg ik deze te pakken?
Het probleen is dat de GeneralModule bij elke client wordt aangemaakt (moet ook) en er dus voor elke client een connectie naar de database wordt gemaakt (moet ook). De Childs worden pas gemaakt als een client app deze pas nodig heeft.

Maar alle Childs moeten ook de ADOConnection van hun GeneralModule krijgen. Hoe krijg ik dit voor elkaar?

Ik had zoiets als dit, maar dat mag niet omdat Self.ADOConnection daar niet beschikbaar is.
code:
1
2
3
4
class function TGeneralModule.Connection: TADOConnection;
begin
  Result := Self.ADOConnection;
end;

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Iemand misschien een idee hoe ik dit voor elkaar kan krijgen?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 09-09 21:25

Creepy

Tactical Espionage Splatterer

Op dinsdag 09 april 2002 14:52 schreef jelmervos het volgende:
Maar alle Childs moeten ook de ADOConnection van hun GeneralModule krijgen. Hoe krijg ik dit voor elkaar?

Ik had zoiets als dit, maar dat mag niet omdat Self.ADOConnection daar niet beschikbaar is.
code:
1
2
3
4
class function TGeneralModule.Connection: TADOConnection;
begin
  Result := Self.ADOConnection;
end;
Als self.ADOCOnnection niet beschikbaar is, hoe benaderd een instantie van TGeneralModule dan een adoconnectie?

Kan je niet bij het aanmaken van je childs de ado connectie meegeven als parameter, zodat je deze weer in een property van de child kan zetten?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Die GeneralModule wordt aangemaakt zodra er een client een connectie opzet, er is dus niet een instanctie van de GeneralModule, alleen de class.

Ook de childs worden aangemaakt zodra een client deze nodig heeft. Het is dus niet zo dat de GeneralModule alle childs maakt zodra hij zelf wordt benaderd.

Nu heeft toch 1 van de childs de ADOConnection nodig van de GeneralModule. Hoe krijgt hij die?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

ff wat uitleg

Een class/klasse/class type is de definitie ve structuur.

Een instantie van een class is een stuk geheugen die voldoet aan de structuur, die door de class is gedefinieerd; Instanties hebben een levensloop; ze worden gecreeerd met Create en vernietigd met Destroy.

Vb:
code:
1
List := TList.Create;

List is een instantie van class TList.

Een class kan ook class functies/procedures hebben; Self wijst in zo'n class functie/procedure niet naar een instantie van een class, maar naar een class.

Bv:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class procedure TMyForm.Execute;
var
  Frm: TMyForm;
begin
  { Frm wijst naar een instantie van class TMyForm, 
    Self wijst naar class TMyForm }
  Frm := Self.Create(nil);
  try
    Frm.ShowModal;
  finally
    Frm.Free;
  end;
end;

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Bedankt voor de uitleg.

Maar nu moet ik dus vanuit de child modules de ADOConnection hebben van de GeneralModule. Maar omdat de GeneralModule per verbinding wordt gemaakt, is de ADOConnection elke keer anders.

Ik kan dus vanuit de child modules wel een class functie aanroepen in de TGeneralModule maar die kan weer niet een ADOConnection (of welk object dan ook) terug geven uit zijn eigenlijk class.

Ik kan ook een gewonen functie maken, maar die is weer niet te benaderen vanuit de childs, omdat er nog geen instancie is van het type TGeneralModule.

Hoe los ik dit op?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Alle child RDM's hebben wel een variable met de GeneralModule erin die de child heeft gemaakt, maar die ziet er zo uit:
code:
1
    FMainDM: IGeneralModule;

En wordt gezet/opgevraagt op deze manier:
code:
1
2
3
4
5
6
7
8
9
function TRelatieModule.Get_MainDM: GeneralModule;
begin
  Result := FMainDM;
end;

procedure TRelatieModule.Set_MainDM(const Value: GeneralModule);
begin
  FMainDM := Value;
end;

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Dus je kunt dus de bij een child behorende instantie van TGeneralModule alleen bekijken via die interface?

Hoe is IGeneralModule gedefinieerd? Zit daar een property ADOConnection ofzo bij?

Ik moet wel zeggen dat ik nooit gewerkt heb met DCOM, dus al die types zeggen mij niets :) Is ook Enterprise versie denk ik?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Yep, Delphi 6 Enterprise

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
De TLB van de server ziet er zo uit:
Afbeeldingslocatie: http://www.endoria.net/upload/index.php/1230379166

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Ow, maar dat wil zeggen dat je zelf methods/properties kunt toevoegen?

Je wilt in de child iets doen met de ADOConnection van een TGeneralModule instantie. Je zou dan een method aan IGeneralModule kunnen toevoegen [en aan TGeneralModule] die dat voor jouw doet.

Je zou ook de ADOConnection kunnen doorgeven dmv een Integer [die eigenlijk een pointer naar de ADOConnection is], maar dat is niet zo netjes denk ik.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik kan wel een property maken die dit terug geeft: struct tag GeneralModule *, maar daar zit dus niet de ADOConnection in, die zit in TGeneralModule.

Eigenlijk is die property er al, in de vorm van de property MainDM die elke child heeft. Dat is een verwijzigen naar de interface van de GeneralModule die die child heeft gemaakt. Ook daar zit dus niet de ADOConnection in.

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Ik bedoelde eigenlijk een property of method aan de interface van IGeneralModule toevoegen..

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Op dinsdag 09 april 2002 20:54 schreef DiFool het volgende:
Ik bedoelde eigenlijk een property of method aan de interface van IGeneralModule toevoegen..
Met wat als resultaat?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Een method DoSomeThingWithADOConnection ofzo, zodat de child kan zeggen:
code:
1
  FMainDM.DoSomeThingWithADOConnection;

en dat TGeneralModule het dan verder afhandelt.

Of een property ADOConnection: Integer zodat de child kan zeggen:
code:
1
2
3
4
5
6
var
  ADOConnection: TADOConnection
begin
  ADOConnection := TADOConnection(Pointer(FMainDM.ADOConnection));
  { En doe dan iets met die ADOConnection }
end;

Ofzo.. Ik weet niet wat je met die ADOConnection wilt doen.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik heb die ADOConnection nodig in de childs omdat elke child gewoon een ADOConnection nodig heeft om Query's richting de database te kunnen doen.

Als je design-time opgeeft dat de ADOConnection op de GeneralModule zit dan werkt het wel, maar dan gebruiken alle childs van alle connecties (clients) de eerste GeneralModule (van de eerste client dus). Gaat die eerste client weg, hebben de overige clients geen connectie meer.

Ik moet dus run-time bij de OnCreate alle ADODataSet's, ADOQuery's en ADOCommand's bijlangs om de Connection te zetten naar de ADOConnection van de GeneralModule die die child heeft gemaakt.

Snap je het nog? :)

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Ik kan het nog redelijk volgen ja :)

Dan zou ik een readonly property ADOConnection in de interface van IGeneralModule maken [van het type integer]. En deze dan in TGeneralModule implementeren door de ADOConnection als integer door te geven.

Maarre - misschien een stomme vraag - kun je het niet zo maken dat de eerste Child het langst blijft bestaan?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ja, dus standaard een client laten verbinden zeg maar.

Dat idee had ik ook al, maar dan gaat alles via 1 ADOConnection, op zich niet zo erg, maar dat was niet de opzet.

Misschien kan ik een lijst (TList) bijhouden van GeneralModules, maar hoe weet ik dan welke hij moet hebben.

Is trouwens een vreemd probleem, omdat ik dacht dat hij standaard wel de goede ADOConnection pakte, immers, elke client krijgt zijn eigen modules (hoofd en Childs).

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Begrijp ik het goed als:
  • Er zijn meerdere clients.
  • Elke client heeft een TGeneralModule en meerdere child modules.
  • Elke child kan de bijbehorende TGeneralModule benaderen door de IGeneralModule interface [=FMainDM]<li> Deze interface kun jij aanpassen. Properties toevoegen enzo.
</li>
Dan voeg je toch gewoon een property ADOConnection aan de interface van IGeneralModule toe, en implementeer je die?

De childs kunnen dan via IGeneralModule bij de ADOConnection van TGeneralModule.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Die punten kloppen ja.

Maar dan voeg ik een property toe aan de IGeneralModule, maar wat moet die als resultaat hebben. Hij moet toch iets terug geven? Het mooiste zou zijn een TADOConnection, maar dat kan dus niet omdat die niet in de lijst staat. Daar staan alleen OLE types ofzo.

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Een integer [ofzo iig 4 bytes] die stiekem een pointer is naar een TADOConnection.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Da's idd een oplossing dan. Ga ik es ff kijken of dat gaat lukken.

Is niet echt een nette oplossing, helaas.

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Ow, zocht je een nette oplossing ;)

Maar wie maakt die childs aan? Kun je dat niet aanpassen, dat je een var in de child hebt die naar de ADOConnection van de bijbehorende TGeneralModule wijst?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Die childs worden dus aangemaakt als een client erom vraagt, maar dat gaat zo:
code:
1
2
3
initialization
  FRelatieRDMFactory := TComponentFactory.Create(ComServer, TRelatieModule,
    Class_RelatieModule, ciInternal, tmApartment);

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
De GeneralModule heeft dit:
code:
1
2
3
initialization
  TComponentFactory.Create(ComServer, TGeneralModule,
    Class_GeneralModule, ciMultiInstance, tmNeutral);

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Tja, daar kun je niet veel mee, denk ik dan :)

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 09-09 12:09

Delphi32

Heading for the gates of Eden

Wil je per se dat je clients via een Interface met je GeneralModule instantie praten? Mij lijkt dat niet handig.

Ik zou het zo oplossen: de TGeneralModule single instance maken.
code:
1
2
3
4
5
6
7
8
9
10
11
12
type TGeneralModule = class (...)
...
[b]implementation[/b]
var TheSingleInstanceGeneralModule: TGeneralModule;

class function TGeneralModule.Connection: TADOConnection;
begin
  if not Assigned(TheSingleInstanceGeneralModule) then begin
    TheSingleInstanceGeneralModule := TGeneralModule.Create(Application);
  end;
  result := TheSingleInstanceGeneralModule.ADOConnection;
end;

Ik hoop dat je hier wat aan hebt. Misschien zie ik iets belangrijks over het hoofd?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Zoiets had ik dus ook, maar dan krijg je dat de eerste client die verbinding maakt de TheSingleInstanceGeneralModule zet. De daarop volgende clients maken tevens gebruik van die variable.
Maar als dan de eerste client zijn verbinding verbreekt, en zijn modules + connecties worden ge-destroy-t, dan hebben de overige clients geen verbinding meer naar de database.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 09-09 12:09

Delphi32

Heading for the gates of Eden

Op woensdag 10 april 2002 00:34 schreef jelmervos het volgende:
Zoiets had ik dus ook, maar dan krijg je dat de eerste client die verbinding maakt de TheSingleInstanceGeneralModule zet. De daarop volgende clients maken tevens gebruik van die variable.
Maar als dan de eerste client zijn verbinding verbreekt, en zijn modules + connecties worden ge-destroy-t, dan hebben de overige clients geen verbinding meer naar de database.
Ja kijk, als je TGeneralModule zijn Single Instance laat creëren, dan mag je natuurlijk niet toestaan dat de clients deze instantie free-en buiten medeweten van TGeneralModule om. Dat is echt vragen om problemen :)

Dus mijn volgende vraag: is het nodig dat de clients hun connectie (die ze aangeleverd krijgen van iemand anders!) zelf vrijgeven?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Maar de GeneralModule wordt dus aangemaakt zodra een client verbinding maakt, en deze wordt weer ge-free-t zodra die client weer disconnect.

Childs worden gemaakt zodra de client deze nodig heeft. Alleen moeten de database componenten op die childs wel naar de goede ADOConnection op hun eigen GeneralModule wijzen.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 09-09 12:09

Delphi32

Heading for the gates of Eden

Op woensdag 10 april 2002 10:25 schreef jelmervos het volgende:
Maar de GeneralModule wordt dus aangemaakt zodra een client verbinding maakt, en deze wordt weer ge-free-t zodra die client weer disconnect.
Ik zit me al tijden af te vragen WAAROM ze gemaakt en gefreed worden door je childs/clients. Het doet bij mij het angstige vermoeden rijzen dat je je GeneralModule als RemoteDataModule hebt gemaakt... klopt dat?
Childs worden gemaakt zodra de client deze nodig heeft. Alleen moeten de database componenten op die childs wel naar de goede ADOConnection op hun eigen GeneralModule wijzen.
MM ja ik geloof dat mn hypothese klopt als ik dit erbij lees... ik wacht ff op je antwoord, en als ik gelijk heb zijn we in 5 minuten klaar.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Alle modules zijn idd RemoteDataModules. Alleen worden de childs als ciInternal en de GeneralModule als ciMultiInstance gemaakt.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 09-09 12:09

Delphi32

Heading for the gates of Eden

Op woensdag 10 april 2002 17:51 schreef jelmervos het volgende:
Alle modules zijn idd RemoteDataModules. Alleen worden de childs als ciInternal en de GeneralModule als ciMultiInstance gemaakt.
Ok. Geef me één goede reden waarom je je GeneralModule als RemoteDatamodule beschikbaar wilt stellen BUITEN je server app. Connection sharing over application boundaries heen lijkt me niet zo'n goeie reden :) dus verzin een ander.

Oplossing: maak je General module gewoon TDataModule en stop die in de AutoCreate van je Project. Dan ben je van alle gedoe af, kan je de general module lekker single instancen zoals eerder beschreven en hoeven je childs de module niet te free-en. Dat gebeurt dan dus ook niet meer automagisch middels het ref-counting mechanisme van de interface logics >:) Beetje spelen met de connection pooling van ADO om te zorgen dat je niet constant een connection naar je server open hebt staan (als dat een issue mocht zijn iig, ik geloof dat ADO dat zelf ook kan regelen).

Ik kan uiteraard niet in jouw project kijken, maar zoals ik het hierboven schrijf heb ik het al tig keer gemaakt en het werkt goed. Mocht je redenen hebben om een andere weg te bewandelen, hoor ik dat graag (ik leer ook graag bij).

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Maar in jou oplossing krijg je dat je 1 verbinding naar de database hebt, op zich niet zo erg, maar is het niet beter dat elke client een eigen verbinding naar de database krijgt.

Overigens zal ik de oplossing van jou wel gaan toepassen, dan is in ieder geval de bug eruit.

Bedankt.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Het werkt perfect hoor! De bug is iig dood, alleen jammer dat alles nu via 1 ADOConnection gaan, of is dit niet echt een nadeel?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 09-09 12:09

Delphi32

Heading for the gates of Eden

Op donderdag 11 april 2002 22:22 schreef jelmervos het volgende:
Het werkt perfect hoor! De bug is iig dood, alleen jammer dat alles nu via 1 ADOConnection gaan, of is dit niet echt een nadeel?
Gaaf dat het werkt, mijn padvindersdaad voor vandaag weer gedaan :7

Alles over 1 ADOConnection:
voordelen
-relatief snel: de verbinding met de db hoeft niet iedere keer opgebouwd te worden, login is al gedaan enzo.
-minder resources nodig dan voor iedere RDM een nieuwe connection

nadelen:
-je verbinding blijft open staan, ik weet niet of ado dat op den duur leuk gaat vinden. Maar ik meen me te herinneren dat ado daar wel creatief mee om kan gaan :)

eigenlijk zie ik verder geen nadelen. Misschien iemand anders?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Aha.

Ik denk dat het nadeel van dat de verbinding lang open staat en dat ADO dit niet cool gaat vinden wel wat mee zal vallen. De server start namelijk embedded zodra een client daarom vraagt (zal 's ochtens zijn), de hele dag wordt er mee gewerkt (is een hele dag lang), en om een uur of 5 sluiten de clients weer en wordt de server natuurlijk ook weer gestopt na de laatste client.

Als een dag niet te lang is voor ADO, en ik denk van niet, dan kan het allemaal wel zo. Ik kan via de DCOM server zelf wel opvragen hoeveel en wie er zijn ingelogd, dus da's niet echt het probleem.

"The shell stopped unexpectedly and Explorer.exe was restarted."

Pagina: 1