|
|
TRDSConnection komponens
ADO paletta 9. rész
|
|
Példaprogram letöltése
8987 bájt
|
Az ADO-val foglalkozó cikksorozatunk utolsó cikkében az ADO technológia egy fontos és eddig nem említett részével, a Remote Data Access-szel foglalkozunk. Az ide vonatkozó komponens a TRDSConnection, melynek segítségével akár olyan alkalmazást is fejleszthetünk, ahol a szerver és klisens alkalmazásunk között az internet szolgáltatja a kapcsolatot.
Mellékelt példa futtatása előtt nyissuk meg a /Delphi5/Demos/Ado/Rds/Rdsserver.dpr Delphi-s példaprogramot, mely a mostani példánk szerver alkalmazása lesz. Ezt egyszer futtassuk, hogy a regisztrációja megtörténjen. A mellékelt példában ehhez a szerverhez készítünk egy saját klienst.
Mi is az a Remote Data Access? Az RDA lehetőséget biztosít olyan alkalmazások készítésére, amely a kliensek számára az Interneten, pontosabban a weben keresztül jelenik meg és ugyanúgy működik, mint a lokális hálózatra telepített hagyományos kliens-szerver alkalmazás. LAN környezetben a kliens bejelentkezik a szerverre, majd a szerver autentikálja a bejelentkezőt legtöbbször annak neve és jelszava segítségével. Végeredményben a szerver egy érvényes felhasználóként fogja azonosítani a klienst és adatbáziskapcsolat épülhet fel közöttük. Amikor a kliens adatot küld a szervernek, a szerver automatikusan azonosítja a küldőt, és a megfelelő adatokat egyszerűen vissza tudja küldeni. A bejelentkezés időtartama alatt a szerver és a kliens között permanens kapcsolat van, ami egy olyan állapotot jelent, amiben a két fél kölcsönösen azonosítani képes egymást a hálózat nyújtotta protokollkészlet felhasználásával.
Ha az alkalmazás kikerül az internetre, ez a metódus tovább nem működik. A HTTP protokoll úgymond 'állapot nélküli', nincs lehetőség a kliens vagy a szerver azonosítására. Ahogy a kliens kérésének megfelelve a szerver elkészíti a válasz html oldalát és visszaküldi, szépen el is felejt mindent a kliensről. Ezt a hiányosságot több eszközzel is áthidalhatjuk. Használhatunk pl. cookie-kat vagy tárolhatunk azonosításra szolgáló elemeket a query string-ben. Sajnos csak az állapotot kezelni nem elegendő, egy kicsit az egész architektúrán módosítani kell. Az ADO kifejezetten egy ilyen architektúra részeként került kifejlesztésre, ez pedig a Microsoft általános módszertana a szétkapcsolt és állapot nélküli környezetekben futó alkalmazások számára, vagyis a Windows Distributed interNet Applications (DNA) architektúra.
LAN környezetben az adatbázis szempontjából érdekes rétegek a következő sorrendben helyezkednek el egymás fölött.
- Felhasználói interfész
- Alkalmazás
- ADO
- Adatszolgáltató réteg (data provider)
- Adattár
Az ADO szerepe egyértelmű, az alkalmazás és az adatforrás közti kapcsolatot teremti meg. Az alkalmazás és a felhasználói interfész közvetlenül beszélgethet egymással. A két réteg lehet a kliens gépen, de az alkalmazás lehet elosztott környezetben is, és ekkor az interfésszel a LAN-on keresztül kommunikál.
Nézzünk egy olyan változatot, ahol a felhasználói interfészt kitesszük az Internetre.
- Felhasználói interfész
- Internet
- Alkalmazás
- ADO
- Adatszolgáltató réteg (data provider)
- Adattár
Ekkor az interfészünk HTTP protokollon keresztül találja meg a szerveren lévő alkalmazást. Az alkalmazás készülhet ASP nyelven, illetve írhatunk CGI vagy ISAPI programot szinte bármelyik programozási nyelven, így Delphi-vel is. Ez ma a legelterjedtebb forgatókönyv web-alapú adatkezelő alkalmazások fejlesztéséhez. Lényegében nem történik más, minthogy távoli hozzáférést biztosítunk a szerver alkalmazáshoz.
A Remote Data Access még egyet csavar a rétegek sorrendjén.
- Felhasználói interfész
- Alkalmazás
- ADO
- Internet
- Adatszolgáltató réteg (data provider)
- Adattár
Láthatjuk, hogy az egész alkalmazás kikerült az internetre és vele együtt az adatmanipulációs műveletek is. Az ADO most a távoli adattárral a neten keresztül kommunikál. Ez tulajdonképpen ugyanaz a mutatvány, mint amit a hagyományos kliens-szerver adatkezelő programok csináltak. Amikor egy adatkezelő Form-ot nyitunk, a szerverről az érintett adatok a hálózaton keresztül az alkalmazást futtató számítógépre töltődnek. Ott a kliens oldali alkalmazás segítségével manipuláljuk azokat, és a változások visszakerülnek a szerverre. Az RDA ez ehhez nagyon hasonló technika azzal a különbséggel, hogy a helyi hálózat helyett itt az internet, a kliens pedig egy böngésző vagy valami saját fejlesztésű alkalmazás.
Előnyök és hátrányok
Az RDA tehát lehetőséget nyújt nekünk az adatkezelő alkalmazásunk Internetre történő kiterjesztésére. Ez a technika eliminálja a második forgatókönyv legnagyobb hátrányát, mégpedig azt, hogy az adatokon történő legkisebb változtatáskor is a szerverhez kell fordulni. Még akkor is, ha egy eredményhalmazt mást rendezés szerint szeretnénk látni. Az RDA a recordset-et cache-eli a kliens gépen, és azon bármilyen adatkezelő műveletet elvégezhetünk, sorrendet változtathatunk, szűrhetünk, stb. hálózati forgalom nélkül.
A recordset persze tartalmazhat több ezer sort is. Ha tehát a kliensünk általában egyetlen rekordot keres, inkább a hagyományos technikát alkalmazzuk, semhogy az összes rekordot átküldjük. Sok alkalmazásnál a két módszer ügyes ötvözete a célravezető.
A távoli adatkezelő (RDA) technikák ma még gyermekcipőben járnak, és meglehetősen gyakran változnak. A Microsoft világban két jelentős terület látszik ebben a témakörben formálódni, a Remote Data Service (RDS) és az XML Data Remoting.
Remote Data Service
Az RDS használatának legfőbb akadálya, hogy mivel a funkciók nagy részét a kliens gépre kell telepíteni, eléggé speciális futtató környezet szükséges hozzá. Ez annyit jelent, hogy az általunk fejlesztett Windows alkalmazások kivételével csak a 4-es vagy magasabb verziószámú Internet Explorer alkalmas RDS kliensként viselkedni.
Tovább nehezíti a helyzetet, hogy az RDS-nek két változata forog közkézen. Az IE4 által támogatott változat a V1.5, míg az IE5 és a Visual Studio 6 már a V2.0-t tartalmazza. Szerencsére a V2.0 Data Access Software Development Kit (http://www.microsoft.com/data/mdac2.htm) tartalmaz olyan eszközt, ami a V2.0 kliens oldali komponenseit automatikusan leküldi az IE4 felhasználóknak is.
Nézzük meg közelebbről, hogyan is működik egy RDS kapcsolat. A szerver gépen az adattár egy OLE-DB provider-hez vagy egy ODBC/OLE-DB driver-hez csatlakozik. A provider vagy driver szolgáltatja az adatokat az RDS DataFactory objektumának. A DataFactory objektum olyan adatirányító, adatformázó metódusokat tartalmaz, amivel az adatokat felkészíti az interneten keresztül történő átvitelre. Ezután az adatok a Web szerverhez kerülnek, és ezen a ponton hagyják el a szerver számítógépet. A kliens oldalon az adatokat az RDS DataSpace objektuma kapja el. Ez az objektum kapcsolatot tart fenn a DataFactory objektummal, elkapja az adatokat és visszaalakítja őket recordset formába. Ahogy a recordset megérkezett, a cache-be kerül a kliens gépen, és átadódik a DataControl objektumnak. Végül, ha szükség van rá, a Data Binding Agent objektum köti össze az adatokat a vizuális vezérlő elemekkel. Ez persze nem kötelező lépés, a kliens oldalra érkező adatokat valamilyen script-el is feldolgozhatjuk.
Ha a vizuális vezérlő elemek megengedik az adatok módosítását (INPUT, SELECT, TEXTAREA, stb.), akkor a változások a cache-ben tárolódnak. A DataControl objektum a felelős azért, hogy egy parancs hatására (SubmitChanges) a változásokat visszaküldje a szervernek, ahol a DataFactory objektum fogja az adatok tényleges módosítását elvégezni.
Biztonság
Amíg az alkalmazás a szerveren futott, a kliensek csak utasításokat küldtek, hogy hogyan is szeretnék módosítani az adatokat, de sosem látták az adatforrást közvetlenül. Az adatbáziskapcsolatra vonatkozó információk is az ASP lapokon, a szerver oldalon voltak megtalálhatók. Az RDS ezzel szemben lehetővé teszi, hogy a kliens közvetlenül az adatforrással beszélgessen. Ezzel persze a kapcsolatot felépítő információk (pl. felhasználói név, jelszó, stb.) is a kliens oldalra kerülnek. Ezért feltétlenül szükséges, hogy az adatforráshoz való hozzáférést a lehető legszigorúbban korlátozzuk, vagyis minden egyes táblára, tárolt eljárásra, nézetre, stb. adjunk explicit jogosultságot a megfelelő felhasználóknak.
Az RDS 2.0 változatában új lehetőséggel bővült a DataFactory objektum a kliensek adatforrás elérésére vonatkozóan. Az MDAC telepítésekor egy msdfmap.ini nevű fájl kerül a Winnt (vagy Windows) könyvtárba. Ebben definiálhatjuk a DataFactory objektumra vonatkozó beállításokat is, amiket az majd a kliens kapcsolódásakor érvényesít. Ez az ini fájl a DataFactory objektum handler-e, és a használatával elrejthetjük a kliens alkalmazás elől a connection string-ünket.
Nézzünk erre egy nagyon egyszerű html példát. Hozzuk létre az NWind nevű ODBC adatforrást (Control Panel/ODBC Data Sources/System DSN fül) és ez mutasson az SQL Serverünk Northwind nevű példaadatbázisára. (Természetesen bármely más adatforrással is kísérletezhetünk.) Készítsünk egy html oldalt a következő tartalommal:
<HTML>
<!- RDS kapcsolat: -->
<OBJECT classid=clsid:BD96C556-65A3-11D0-983A-
00C04FC29E33 id=myCustomers VIEWASTEXT>
<PARAM name="SQL" value="SELECT CustomerID,
CompanyName FROM Customers">
<PARAM name="Connect" value="Data Source=NWind;
user id=sa; password=;">
<PARAM name="Server" value="http://localhost">
</OBJECT>
<BODY>
<!-- Eredményhalmaz: -->
<TABLE datasrc="#myCustomers" border="1" >
<TR>
<TD><SPAN datafld="CompanyName">
</SPAN></TD>
<TD><SPAN datafld="CustomerID">
</SPAN></TD>
</TR>
</TABLE>
</BODY>
</HTML>
Amikor az oldal betöltődik, az IE elkészíti a DataControl objektum egy példányát és a myCustomer azonosítót adja neki. A Connect paraméter hivatkozik az ODBC adatforrásra egy szép kis Connection string-gel. A Server paraméter lehet egy http vagy https URL, lehet a számítógép neve, ha DCOM protokollról van szó.
Világos, hogy biztonsági szempontból nem valami jó a megoldás, hiszen kliens oldalon bárki belenézhet a kódba, és az információk birtokában kedvére szétnézhet az adatbázisban. A megoldás a DataFactory handler használata. Keressük meg az Msdfmap.ini fájlt és szúrjuk be a következő két szakaszt:
[connect Valami]
Access=ReadWrite
Connect="DSN=NWind;uid=sa;pwd=;"
[SQL Akarmi]
SQL="SELECT * FROM Customers"
A html lapunk ennek megfelelően így fog kinézni:
<HTML>
<!- RDS kapcsolat: -->
<OBJECT classid=clsid:BD96C556-65A3-11D0-983A-
00C04FC29E33 id=myCustomers VIEWASTEXT>
<PARAM name="Handler" value="MSDFMAP.Handler,
msdfmap.ini">
<PARAM name="SQL" value="Akarmi">
<PARAM name="Connect" value="data source=Valami">
<PARAM name="Server" value="http://localhost">
</OBJECT>
<BODY>
<!-- Eredményhalmaz: -->
<TABLE datasrc="#myCustomers" border="1" >
<TR>
<TD><SPAN datafld="CompanyName">
</SPAN></TD>
<TD><SPAN datafld="CustomerID">
</SPAN></TD>
</TR>
</TABLE>
</BODY>
</HTML>
Látható, hogy a connection string és maga az SQL utasítás is láthatatlan a kliens oldalon, pusztán egy hivatkozás, ami az Msdfmap.ini fájlban kap értéket.
Delphi
A TRDSConnection objektum nem más, mint az RDS DataSpace objektumának VCL reprezentációja. Mint korábban írtuk, a DataSpace objektum a kliens oldalon kezeli a szervertől érkező adatfolyamot. A programban a TADOConnection objektum helyett használhatjuk. Alapesetben a komponens az RDS DataFactory objektumával próbál meg kapcsolatot teremteni.
A példaalkalmazásunk igen egyszerű, egy ADODataset komponenst TDBGrid-hez kötünk, és az RDSConnection property-jén keresztül egy TRDSConnection komponenshez kapcsoljuk. Így az adathalmaz recordset-je a TRDSConnection által felépített kapcsolaton keresztül érkezik meg. Két lehetőségünk van, a DataFactory objektumhoz csatlakozunk, vagy business object-et írunk, és ahhoz csatlakozunk. A Delphi példaprogramjai között találunk egy egyszerű alkalmazás szervert (/Delphi5/Demos/Ado/Rds/Rdsserver.dpr), azzal kísérletezhetünk, ha nincs kedvünk sajátot írni.
Property-k, metódusok és események
Property-k:
AppServer: OLEVariant típusú property, az alkalmazásszerver interfészére mutat. Legtöbbször nincs szükség a használatára.
ComputerName: Azt a számítógépet kell itt azonosítanunk, ahol az úgynevezett business object, vagy a DataFactory objektum tartózkodik. A kapcsolatfelvételhez használhatunk HTTP, HTTPS és DCOM protokollokat. Ha HTTP(S)-t használunk, a ComputerName property-be annak a számítógépnek az URL-jét kell beírni, ahol a business object, pl. az IIS van. DCOM esetében a gép nevét kell beírnunk.
DataSpaceObject: A property az RDS DataSpace objektumának interfésze. A DataSpace közvetlen elérésére csak akkor van szükség, ha olyan metódust akarunk elérni, amit az RDSConnection komponens nem valósít meg.
InternetTimeOut: Ha a kapcsolatfelvételhez HTTP vagy HTTPS protokollt használunk, meghatározhatjuk, hogy kérésre mennyi időn belül szeretnénk választ kapni. Ha a property-ben (ezredmásodpercben) beállított idő lejár, a művelet megszakad.
ServerName: A business object ProgID-ját kell itt megadnunk. Alapértelmezett értéke RDSServer.DataFactory.
Connected: Boolean property, a kapcsolat állapotát mutatja. True-ra álltásával a kapcsolat felépül, False-ra állításával lebomlik. True-ra állítás esetén először kiváltódik a BeforeConnect esemény, lefut a DoConnect metódus majd kiváltódik az AfterConnect esemény. A LoginPrompt értékétől függően a login ablak is megjelenhet. False-ra állításkor a BeforeDisconnect esemény után a DoDisconnect metódus fut le, végül az AfterDisconnect esemény.
DataSetCount: Az RDSConnection objektumhoz rendelt aktív adathalmazok száma. Magukat az adathalmazokat a DataSets property tartalmazza. A property-t a TCustomConnection komponens definiálja, és konkrét megvalósítása a leszármazott komponenstől függ. Az ADO komponensek csak az aktív adathalmazokat számolják össze, de a MIDAS komponensek az összes kapcsolódó adathalmazt.
DataSets: Azon adathalmaz komponensek listája, amelyek az RDSConnection-t használják a csatlakozáshoz. A lista elemeinek számát a DataSetCount property tartalmazza.
LoginPrompt: Boolean property, a TCustomConnection definiálja. Ha értéke True, a csatlakozáskor megjelenik a login ablak, egyébként nem. Hogy pontosan mikor jelenik meg az ablak, az a leszármazott connection objektumtól függ. A TCustomConnection objektum ugyanis nagyon kurtán elintézi a DoConnect metódust:
procedure TCustomConnection.DoConnect;
begin
end;
A TDatabase és a TADOConnection esetén a login ablak a BeforeConnect esemény után és az AfterConnect esemény előtt jelenik meg, hacsak nem valósítjuk meg az OnLogin eseményt. Ha megvalósítjuk, akkor a login ablak helyett az itt megírtak jelennek meg. Az OnLogin esemény csak akkor jön létre, ha a LoginPrompt értéke True.
MIDAS kapcsolat esetén a login ablak az OnGetUserName esemény után és a BeforeConnect, AfterConnect és OnLogin események előtt jelenik meg.
Ha a LoginPrompt értéke False, az alkalmazásnak gondoskodnia kell a felhasználói név és a jelszó beállításáról. TDatabase esetén ez a Params property-n keresztül történik, ADO kapcsolatnál a ConnectionString-ben, MIDAS esetében ez teljesen egyedi megvalósítást igényel.
StreamedConnected: Belső használatú, boolean típusú property. True értéke azt jelzi, hogy a Connected property True volt, amikor a komponens a stream-ről töltődött. Használatára azért van szükség, hogy a komponens addig ne építse fel a kapcsolatot, amíg minden adatmodul be nem töltődött a memóriába. Valahogy így:
procedure TCustomConnection.Loaded;
begin
inherited Loaded;
try
if FStreamedConnected then SetConnected(True);
except
[...]
end;
end;
Metódusok:
GetRecordset: A metódus letölti a recordset-et a business object-ről. Automatikusan meghívódik, amikor egy adathalmazt kapcsolunk az RDSConnection komponenshez. A metódusnak két paramétere van, CommandText: WideString és ConnectionString: WideString. Ha business object-hez csatlakozunk, a CommandText paraméterben kell átadnunk a business object nevét. Ha DataFactory objektumhoz csatlakozunk, a CommandText paraméter tartalmazza a futtatandó lekérdezést, a ConnectionString pedig a kapcsolódás paramétereit. Mindez kódban:
begin
if FIsAppServer then
Result := GetFromProperty else
Result := GetFromDataFactory;
end;
A recordset DataFactory használata esetén így áll elő:
Result := IUnknown(AppServer.Query(ConnectionString,
CommandText, 0)) as _Recordset;
Business object használata esetén:
FServDisp := IUnknown(FAppServer)
as IDispatch;
FServDisp.Invoke(DispID, GUID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYGET, DispParams, @VarResult,
@ExcepInfo, nil);
Result := IUnknown(VarResult) as _Recordset;
Close: Lezárja a kapcsolatot. Egyenértékű a Connected property False-ra állításával.
DoConnect: Felépíti a kapcsolatot.
DoDisconnect: Lezárja a kapcsolatot.
GetConnected: A Connected property értékével tér vissza.
GetDataSet: A DataSets tömbből a metódus paraméterében megadott sorszámú adathalmazt adja vissza.
GetDataSetCount: A DataSetCount property értékét adja vissza.
Loaded: Belső metódus, inicializálja az RDSConnection komponenst, miután a Form minden objektuma betöltődött a memóriába.
Open: Felépíti a kapcsolatot. Egyenértékű a Connected property True-ra állításával.
RegisterClient: Belső használatú metódus, regisztrálja az RDSConnection komponenst használó objektumot.
SendConnectEvent: Minden regisztrált (RegisterClient) objektumot értesít, ha a kapcsolat felépül vagy lezáródik.
SetConnected: A Connected property értékét állítja be.
UnRegisterClient: A korábban regisztrált objektumot törli a listáról, így az többé nem lesz hozzárendelve az RDSConnection komponenshez.
Események:
AfterConnect: A kapcsolat felépülése után váltódik ki.
AfterDisconnect: A kapcsolat lezárása után váltódik ki.
BeforeConnect: A kapcsolat felépülése előtt váltódik ki.
BeforeDisconnect: A kapcsolat lezárása előtt váltódik ki.
OnLogin: A kapcsolat megnyitásakor hívódik meg, ha a LoginPrompt property értéke True. A LoginPrompt property-nél bővebben írtunk róla.
|
Könyv
Ez a cikk megtalálható ebben a könyvben:
Delphi Software Offline 2001 évkönyv 133. oldal
Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!
|