Delphi - TCustomADODataSet objektum

ADO paletta 4. rész

forráskód letöltése
A cikkben az ADO komponenspaletta adathalmaz komponenseinek ősével, a TCustomADODataSet komponens bemutatásával foglalkozunk. A komponens az összes fontos adatmanipulációs műveletet megvalósítja, így a leszármazott komponensekre már kevés feladat hárul. Példaprogram

A programban arra mutatunk példát, hogy a TCustomADODataSet objektum eseményei mikor és hogyan kerülnek meghívásra. Az SQL Server NorthWind adatbázisának Orders és Order details tábláját hozzuk master-detail viszonyba, és megjelenítjük őket két DBGrid-ben. A DBGrid-ben mászkálva és a rekordokat módosítva események váltódnak ki, amiket a jobb oldali ListBoxban jelenítünk meg.

A ConnectionString alapértelmezett értéke:
  Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;
  Initial Catalog=Northwind;Data Source=NALA

SQL Server esetén a Data Source paraméter értékét le kell cserélni a gazdaszámítógép nevére. Ha nincs SQL Server a gépen, meg lehet próbálkozni a NorthWind Access változatával. A ConnectionString ekkor valami ilyesmi lesz:
  
Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;
Data Source=C:\Program Files\Microsoft Data Access SDK\
     Samples\ADO\NWIND.mdb;

A programban arra is látunk példát, hogy hogyan használhatjuk fel az ADO ConnectionString szerkesztő ablakát:
  if EditConnectionString(ADOConnection) then
  begin
    ConnectionString.Text := ADOConnection.ConnectionString;
    ConnectionStringClick(Sender);
  end;

Az EditConnectionString nevű függvényre a Delphi5/Source/Property Editors könyvtár adoconed.pas unitjában bukkanhatunk rá.

Ha nincs Northwind adatbázis, bármi mással is próbálkozhatunk. A master-detail viszony sincs beégetve, a következő pár sor állítja elő:
  MasterTable.TableName := 'Orders';
  DetailTable.MasterSource := nil;
  MasterTable.Open;
  DetailTable.TableName := 'Order Details';
  DetailTable.MasterFields := 'OrderId';
  DetailTable.MasterSource := mtSource;
  DetailTable.Open;
A 'Recordset property-k' gomb lenyomásával a MasterTable nevű ADOTable komponens RecordSet-jének tulajdonságai között böngészhetünk.
  with MasterTable.RecordSet.Properties do
  for i := 0 to Count - 1 do
  begin
    try Value := Item[i].Value; except Value := '' end;
    lb1.Items.Add(Item[i].Name + ':' + Value);
  end;


TCustomADODataSet objektum

A TCustomADODataSet az ADO adathalmaz (TADODataSet, TADOTable, TADOQuery, TADOStoredProc) komponensek őse. Mindazokat a metódusokat, property-ket tartalmazza, amelyekkel az ADO adatforrások megszólíthatók, kezelhetők. Közvetlen példányosítására nincs szükség, használjuk mindig a leszármazottakat helyette. Éppen ezért a metódusok és property-k egy része absztrakt, vagyis deklarálva vannak, de implementálva nincsenek. Ez a feladat a leszármazott komponensekre hárul.

A TCustomADODataSet komponensnek nincs ADO megfelelője. Mint azt korábban már írtuk, az ADO gyakorlatilag 3 objektumra támaszkodik, és ennek a három objektumnak a megfelelői a TADOConnection, TADODataSet és a TADOCommand. A másik három adathalmaz objektum csak azért kapott helyet a palettán, mert logikailag beleillik a Delphi adatbáziskezelő komponenseinek a struktúrájába, de a műveleteket ők is a három alapvető objektumon keresztül valósítják meg.


Lássuk a property-ket, metódusokat, eseményeket!

Property-k:

BlockReadSize: Blokkos olvasás esetén az egyszerre beolvasandó rekordok számát állíthatjuk itt be. Blokkos üzemmódban (ha a BlockReadSize értéke nagyobb, mint 0 ) például a Next metódus hatására a vizuális adatkomponensek nem frissülnek, az események nem váltódnak ki, tehát gyorsan végig lehet nyálazni az adatbázist. Ilyenkor a State property értéke dsBlockRead. Ha a BlockReadSize értéke nulla, a blokkos olvasási mód ki van kapcsolva.
A dolog nem ADO találmány, a BDE datasetek is tudják. Ha megnézzük a DB unitban a TDataSet.Next metódust, ezt találjuk:
procedure TDataSet.Next;
begin
  if BlockReadSize > 0 then
    BlockReadNext else
    MoveBy(1);
end;
CacheSize: Az adathalmaz cache területének mérete. Értéke azt jelenti, hogy az adathalmaz hány rekordja kerül egyszerre pufferelésre a memóriában. Ha a sormutató túlmutat a pufferben lévő rekordokon, újabb CacheSize-nyi mennyiségű rekord kerül a pufferbe. Alapértelmezett értéke 1.

CanModify: Read-only, boolean típusú tulajdonság. Értéke True, ha az adathalmaz módosítható, False, ha csak olvasható.

CommandText: A végrehajtandó SQL utasítás szövegét tartalmazza. A komponens az SQL utasításokat az ADO Command objektumával hajtja végre. Az utasítás szövege tartalmazhat egy normál SQL utasítást, de hivatkozhatunk itt táblára vagy tárolt eljárásra is. Végrehajtása az Open metódus hívásával történik.
Mivel a komponens az ADO-val jórészt a Command objektumon keresztül érintkezik, sok property és metódus ismerős lesz.

CommandTimeout: A parancs végrehajtására szánt időt korlátozhatjuk másodpercben. Ha az itt beállított idő lejár, a parancs végrehajtása sikertelen.

CommandType: A CommandText mezőbe írt SQL parancs típusát állítjuk itt be. Az alapértelmezett érték: cmdUnknown. Ha így hagyjuk, az ADO maga dönti el, hogy mi van a CommandText-ben, és hogyan kell feldolgozni. A nagyobb teljesítmény érdekében célszerű nekünk kitölteni. A lehetséges értékek a következők:
  • cmdUnknown: A CommandText property-ben szereplő parancs típusa ismeretlen.
  • cmdText: A parancs egy SQL utasítás.
  • cmdTable: A CommandText property egy tábla nevét tartalmazza.
  • cmdStoredProc: A CommandText property egy tárolt eljárás nevét tartalmazza.
  • cmdFile: A CommandText property egy elmentett recordset nevét tartalmazza.
  • cmdTableDirect: A CommandText property egy tábla nevét tartalmazza. Abban különbözik a cmdTable-től, hogy ott az ADO egy SQL query-vel kérdezi le a tábla összes oszlopát, itt pedig a provider-t utasítja erre.


Connection: Akkor kell beállítani, ha TADOConnection komponensen keresztül kapcsolódunk az adatbázisra.

ConnectionString: Közvetlen adatbázis kapcsolat esetén a kapcsolódás paramétereit kell itt beállítanunk. Részletesen lásd a 2. fejezetben, a Connection objektum tárgyalásánál.

CursorLocation: A kurzor helyét lehet beállítani. Ha értéke clUseServer, a kurzor a szerveroldalon jön létre, ha clUseClient, akkor a kliens oldalán.

CursorType: Az ADO adathalmaz által használt kurzor típusát állítja be. A kurzortípus határozza meg a rekordset bejárásának irányát és a változtatások láthatóságát más felhasználók számára. Öt típust állíthatunk be.
  • ctUnspecified: A kurzortípus nincs beállítva.
  • ctOpenForwardOnly: Az eredményhalmazon csak előrefelé lépkedhetünk, vissza nem. Hatékonyabb, mint a mindkét irányból bejárható eredményhalmaz.
  • ctKeyset: Más felhasználók által beszúrt rekordok nem látszanak és a más felhasználók által törölt rekordok elérhetetlenek.
  • ctDynamic: Más felhasználó minden módosítása látszik, az eredményhalmaz oda-vissza bejárható.
  • ctStatic: A rekordok statikus másolatát jelenti. Más felhasználók változtatásai nem látszanak.


DesignerData: Belső használatú property, ne használjuk. Az SQL utasítások ezen változón keresztül jutnak el az ADO-ig.

EnableBCD: Boolean tulajdonság. Ha értéke True, a numerikus és decimális mezők BCD értékként kerülnek tárolásra, egyébként lebegőpontosként.

ExecuteOptions: Az ExecuteOptions paraméter beállításával a futás karakterisztikáját szabályozhatjuk. Értéke lehet eoAsyncExecute, eoAsyncFetch, eoAsyncFetchNonBlocking vagy eoExecuteNoRecords.
  • eoAsyncExecute: a parancs aszinkron módban fut.
  • eoAsyncFetch: azt jelzi, hogy miután az Initial Fetch Size (Connection) property-ben meghatározott számú sor letöltődött, a fennmaradó sorok aszinkron módon töltődnek le. Ha a keresett sor még nem töltődött le, az alkalmazás fő végrehajtási szála megáll (blokkolódik), amíg a rekord elérhetővé nem válik.
  • eoAsyncFetchNonBlocking: Ugyanazt jelenti, mint az előző, csak a végrehajtási szál soha nem áll meg fetch alatt.
  • eoExecuteNoRecords: nem kérünk visszatérési értéket. Ha mégis lenne, azt az objektum eldobja.


Filter: A BDE adathalmazoknál megszokott szűrő-funkcionalitást nyújtja, vagyis az alkalmazás számára csak azokat a rekordokat teszi elérhetővé, amik a szűrőfeltételnek eleget tesznek.

Filtered: Boolean tulajdonság. True érték mellett a szűrés funkció be van kapcsolva és érvényre jut a Filter property-ben megadott feltétel, egyébként nem.

FilterGroup: Ha az adathalmaz kötegelt feldolgozási módban van (update batch mode), akkor az egyes rekordot update állapotának függvényében tudunk szűrni. A FilterGroup különböző értékeivel a következő csoportokat válogathatjuk le:
  • fgUnassigned: Nincs szűrés. Az ADO belső használatra tartja fent.
  • fgNone: Nincs szűrés, minden sor látszik.
  • fgPendingRecords: Csak azok a sorok jelennek meg, amiket módosítottunk, és a módosításokat nem jutattuk érvényre vagy a módosítási igényt nem töröltük az UpdateBatch vagy CancelBatch metódus hívásával.
  • fgAffectedRecords: Az utolsó update óta valamilyen műveletben érintett rekordok látszanak.
  • fgFetchedRecords: Az update cache-ben lévő rekordok látszanak.
  • fgPredicate: Az éppen törölt rekordok látszanak.
  • fgConflictingRecords: A módosított, de az érvényesítés során hibára futó rekordok látszanak.

A FilterGroup használata előtt célszerű megvizsgálni, hogy a LockType property ltBatchOptimistic-ra van-e állítva.

IndexFieldCount: Az index kulcsot alakító mezők számát tartalmazza ez a tulajdonság.

IndexFields: Az index kulcsot alakító mezők tömbje.

LockType: Az adathalmaz megnyitásakor használt zárolási stratégiát meghatározó tulajdonság. Ötféle érték közül választhatunk:
  • ltUnspecified: A lock típusa nincs meghatározva.
  • ltReadOnly: Csak olvasható lock, az adatok nem módosíthatók.
  • ltPessimistic: Pesszimista lock, a provider mindent megtesz, hogy a rekord szerkesztése sikeres legyen, és általában zár alá helyezi már a szerkesztés legelején.
  • ltOptimistic: Optimista lock, a zár csak akkor kerül fel a rekordra, amikor a módosítás érvényre jut.
  • ltBatchOptimistic: Optimista batch update, kötegelt feldolgozási mód.

Csak olyan zárolási sémát használhatunk, amit a provider is támogat. Az ltUnspecified érték használatával a provider alapértelmezett zárolási metódusát fogjuk használni.

MarshalOptions: Amikor kliens oldali kurzort használunk, a módosított adatokat vissza kell küldeni a szerverre. A MarshalOptions property beállításával meghatározhatjuk, hogy a lokális adathalmaz mely rekordjai kerüljenek vissza a szerverre. Két értéket használhatunk, moMarshalAll-t, ha az összes adatot visszaküldjük, és moMarshalModifiedOnly-t, ha csak a megváltozott rekordokat küldjük vissza.

MaxRecords: Az eredményhalmaz rekordjainak számát korlátozhatjuk ebben a property-ben.

ParamCheck: Booelan változó, ha értéke True, minden olyan esetben, amikor a CommandText property-ben lévő SQL utasítás megváltozik, újra generálódik a paraméterlista az utasítás szövegében lévő :Param típusú paraméterhivatkozások alapján.

Parameters: A CommandText-ben lévő SQL utasítás paramétereit tartalmazó property.

Prepared: Boolean változó. Ha értéke True, az SQL utasítás futása előtt az ADO előkészíti az adatbázist ugyanúgy, ahogy a BDE Prepared is teszi. Alapértelmezett értéke False.

Properties: Az ADO RecordSet objektum Properties kollekciójának közvetlen elérésére szolgál. A Properties kollekció Property objektumok gyűjteménye, minden Property objektum a RecordSet objektum egy jellemző paraméterét írja le.

RecNo: Az aktuális rekord pozíciója az eredményhalmazban. A property-t írhatjuk is.

RecordCount: Az eredményhalmaz rekordjainak száma.

RecordSet: A property direkt hozzáférést biztosít az ADO RecordSet objektumához. Akkor van rá szükség, ha egy olyan metódust szeretnénk elérni, amit a Delphi adathalmaz komponensei nem valósítanak meg.

RecordSetState: Az adathalmaz állapotát jelző property. Értéke lehet stClosed, stOpen, stConnecting, stExecuting és stFetching.

RecordSize: Az adathalmaz egy rekordjának mérete. Csak olvasható, absztrakt property, ebben a komponensben mindig 0. A leszármazott objektumok valósítják meg.

RecordStatus: Az aktuális sor állapotát tartalmazó property. Kötegelt feldolgozáskor van értelme és a következő értékeket veheti fel: sOK, rsNew, rsModified, rsDeleted, rsUnmodified, rsInvalid, rsMultipleChanges, rsPendingChanges, rsCanceled, rsCantRelease, rsConcurrencyViolation, rsIntegrityViolation, rsMaxChangesExceeded, rsObjectOpen, rsOutOfMemory, rsPermissionDenied, rsSchemaViolation és rsDBDeleted.

Sort: Az adathalmaz sorrendezését tartalmazza.

Metódusok:

BookmarkValid: A függvény a paraméterként átadott bookmark érvényességét ellenőrzi. Ha érvényes, visszatérési értéke True.

CancelBatch: Kötegelt feldolgozás esetén a még nem érvényesített update-eket görgeti vissza. Paraméterként megadhatjuk, hogy az összes függőben lévő update közül melyeket kell visszagörgetni:
  • arCurrent: Csak az aktuális rekord update-je törlődik, a többi nem.
  • arFiltered: Csak az érvényben lévő szűrési feltételnek megfelelő rekordok update-je törlődik, a többi nem.
  • arAll: Minden rekord update-je törlődik.


CancelUpdates: Az összes függőben lévő update törlődik.

Clone: Megduplázza a parameterként átadott adathalmaz recordset-jét.

CompareBookmarks: Két bookmark összehasonlítását végzi. Az eredményt egy egész típusú visszatérési érték jelzi, ha 0, akkor a két bookmark ugyanaz, ha -1, az első paraméterben meghatározott bookmark kisebb, ha 1, akkor nagyobb.

Create: A komponens absztrakt konstruktora.

CreateBlobStream: Blob stream-et hoz létre blob mezők számára. Paraméterként át kell adnunk a blob mező nevét és azt, hogy a stream-en írni (bmRead), olvasni (bmWrite) vagy mindkettőt (bmReadWrite) szeretnénk.

DeleteRecords: A metódus rekordokat töröl a recordset-ből. Hogy hány és mely rekordokról van szó, azt a paraméter dönti el:
  • arCurrent: Az éppen kiválasztott rekord törlődik.
  • arFiltered: A szűrőfeltételnek megfelelő rekordok törlődnek.
  • arAll: A recordset minden egyes rekordja törlődik.


Destroy: A komponens destruktora.

FilterOnBookmarks: Csak a bookmark-kel megjelölt rekordok jelennek meg. Hívásakor a Filter property-ben beállított szűrőfeltétel törlődik, a FilterGroup property fgUnassigned lesz és a Filtered property True-ra változik.

GetBlobFieldData: A paraméterben meghatározott mező értékét a pufferbe tölti. A leszármazott objektumok használják blob mezők letöltéséhez.

GetFieldData: A paraméterben meghatározott mező értékét a pufferbe tölti.

IsSequenced: A függvény azt vizsgálja, hogy a tábla rekordsorszámai folytonosak-e vagy sem. Ha a függvény visszatérési értéke True, vagyis a sorszámok folytonosak, bátran használhatjuk a RecNo property-t az adathalmaz bejárására.

LoadFromFile: Elmentett recordset-et olvashatunk vissza fájlból. A metódus egyetlen paramétere a fájl neve.

Locate: A BDE Locate-tel megegyező metódus. Kikeresi a megfelelő rekordot és azt teszi aktuálissá. Boolean visszatérési értéke jelzi, hogy a keresés sikeres volt-e.

Lookup: A BDE Lookup-al megegyező metódus. A visszatérési érték a keresés eredménye lesz és az aktuális rekord pozíciója nem változik.

NextRecordset: Ha egy összetett parancs vagy egy tárolt eljárás egyszerre több recordset-et is visszaad, az egyes recordset-eken a NextRecordset metódussal lépegethetünk végig.

Requery: A metódus frissíti a rekordset-et a parancs újbóli futtatásával.

SaveToFile: A recordset-et fájlba menthetjük. Paraméterként a fájl nevét és formátumát kell megadnunk. Két formátumot használhatunk, pfADTG paraméterrel ADTG-t (Advanced Data Tablegram), pfXML-lel XML-t.

Seek: Keresés index alapján. Paraméterként a keresett értéket és a keresés módját kell megadnunk. A keresés az aktuális index alapján történik. Boolean visszatérési érték jelzi a keresés sikerességét. Ha a Seek nem találja meg a megadott értéket, a rekordmutató az adathalmaz végére fog mutatni. Hatféle keresési mód közül választhatunk:
  • soFirstEQ: A rekordmutató az első megtalált rekordra mutat, vagy ha nincs ilyen, az adathalmaz végére.
  • soLastEQ: A rekordmutató az utolsó megtalált rekordra mutat, vagy ha nincs ilyen, az adathalmaz végére.
  • soAfterEQ: A rekordmutató a keresett rekordon áll meg, vagy ha nincs ilyen, rögtön a következő rekordon.
  • soAfter: A rekordmutató a keresett rekord után áll meg.
  • soBeforeEQ: A rekordmutató a keresett rekordon áll meg, vagy ha nincs ilyen, akkor közvetlenül előtte.
  • soBefore: A rekordmutató a keresett rekord előtt áll meg.


Supports: Boolean visszatérési értékkel jelzi, hogy a recordset támogat-e bizonyos, a paraméterben meghatározott kurzorműveleteket.

UpdateBatch: Kötegelt feldolgozás esetén a még nem érvényesített update-eket juttatja érvényre. Paraméterként megadhatjuk, hogy az összes függőben lévő update közül melyeket kell érvényesíteni:
  • arCurrent: Csak az aktuális rekord update-je érvényesül.
  • arFiltered: Csak az érvényben lévő szűrési feltételnek megfelelő rekordok frissülnek, a többi nem.
  • arAll: Minden rekord update-je érvényre jut.


UpdateStatus: Az aktuális rekord update-állapotát mutatja meg. Ez négyféle lehet:
  • usUnmodified: A aktuális rekordnak nincs cache-elt update-je.
  • usModified: A aktuális rekord módosítva lett, és a módosítás még nincs érvényre juttatva.
  • usInserted: Az aktuális rekord be lett szúrva, de a művelet még nincs érvényre juttatva.
  • usDeleted: Az aktuális rekord egy törölt rekord, de a törlés még nincs érvényre juttatva.


Események:

OnEndOfRecordset: Az esemény akkor váltódik ki, ha a rekordmutató elhagyja az utolsó rekordot. A Delphi adatnavigációs utasításai nem tudják kiváltani ezt az eseményt, mert működés közben vizsgálják az Eof property-t, és nem tudnak kimozogni az adathalmazból. Ha a RecordSet property-t közvetlenül programozzuk, akkor előidézhetjük az eseményt.

OnFetchComplete: Az esemény akkor hívódik meg, ha az összes rekord letöltődött a recordset-be. Az adathalmaz Open metódusa is kiváltja.

OnFetchProgress: Aszinkron adatletöltés alatt periodikusan tüzel. Progress paraméterében mutatja a letöltött rekordot számát, MaxProgress paraméterében pedig az összes letöltendő rekordszámot. A két érték segítségével kiszámolhatjuk, hogy a letöltés hány százaléknál tart.
procedure TForm1.ADODataSet1FetchProgress(DataSet: 
   TCustomADODataSet; Progress, MaxProgress: Integer; 
   var EventStatus: TEventStatus);
begin
  Caption := 'Percent complete: ' + IntToStr(
      Trunc(Progress / MaxProgress * 100)) + '%';
  Application.ProcessMessages;
end;
OnFieldChangeComplete: Az esemény akkor hívódik meg, ha egy mező értéke megváltozik.

OnMoveComplete: Akkor keletkezik, ha a rekordmutató megváltozik. A First, Last, Next, Prior, MoveBy, Insert, Delete, Post, Requery és Resynch metódusok mind kiválthatják.

OnRecordChangeComplete: Akkor keletkezik, ha a recordset egy vagy több sora megváltozik.

OnRecordsetChangeComplete: Akkor keletkezik, ha a recordset objektum megváltozik.

OnWillChangeField: Egy mező megváltoztatása előtt hívódik meg.

OnWillChangeRecord: Egy rekord megváltoztatása előtt hívódik meg.

OnWillChangeRecordset: A rekordset megváltoztatása előtt hívódik meg.

OnWillMove: Mielőtt a rekordmutató elmozdulna a recordset-ben, kiváltódik az OnWillMove esemény.

ADO paletta cikksorozat