TClientDataSet je komponenta datové množiny určená
pro práci bez podpory BDE. Místo BDE je používána DBCLIENT.DLL, která je
mnohem menší a jednodušší pro instalaci a konfiguraci. Komponenty databáze
s klientskými datovými množinami nepoužíváme, protože nemají databázové
připojení.
Klientské datové množiny poskytují všechen datový přístup,
editace, navigace a filtrování zděděné od TDataSet. Nicméně aplikace,
která používá klientské datové množiny, musí poskytnout mechanismus kterým
klientská datová množina čte data a zapisuje aktualizace. Klientské datové
množiny toto poskytují jednou z následujících možností:
-
Čtení z a zápis do plochého souboru zpřístupněného přímo
z komponenty klientské datové množiny. Je to mechanismus používaný databázovými
aplikacemi plochých souborů.
-
Čtením z jiné datové množiny. Klientské datové množiny poskytují
různé mechanismy pro kopírování dat z jiných datových množin. Toto je popsáno
v Kopírování dat z jiných
datových množin.
-
Používání rozhraní IProvider k získání dat z a odesílání
aktualizací na vzdálený aplikační server. Je to mechanismus použitý klienty
ve více vrstvových databázových aplikacích. Více vrstvovými databázovými
aplikacemi se budeme zabývat v následující kapitole.
Tyto mechanismy mohou být kombinovány v jedné aplikaci používající
model aktovky. Uživatel získá potřebná data, uloží je do souboru a může
s nimi pracovat samostatně. Později klientská aplikace aplikuje změny z
lokální kopie dat na aplikační server. Aplikační server je zpracuje a vrací
chyby klientské datové množině pro zpracování. Toto je popsáno v Podpora
aktovkového modelu.
Následující body poskytují více informací o práci s klientskými
datovými množinami:
Databázové aplikace
plochých souborů
Databázové aplikace plochých souborů jsou jednovrstvové aplikace,
které používají TClientDataSet k reprezentaci všech svých datových
množin. Klientské datové množiny drží všechna svá data v paměti, což znamená,
že tento typ aplikací není vhodný pro velké datové množiny. Databázové
aplikace plochých souborů nevyžadují BDE. Místo BDE používají pouze DBCLIENT.DLL.
Tento typ aplikací tedy sám nepotřebuje tolik paměti jako aplikace založené
na BDE. Protože používají pouze DBCLIENT.DLL, jejich šíření je snazší,
protože nemusí instalovat, konfigurovat a udržovat BDE.
Protože tyto aplikace nepoužívají BDE, nejsou určeny
pro více uživatelský přístup. Datové množiny jsou zcela vyhrazené této
aplikaci. Data mohou být ukládána na disk a později opět zaváděna, ale
nemají zabudovanou ochranu chránící před přepsáním jiným uživatelem.
Klientská datová množina (umístěná na stránce MIDAS
Palety komponent) je základem databázových aplikací plochých souborů. Poskytuje
podporu pro většinu databázových operací prováděných datovými množinami
založenými na BDE. Používáme stejné komponenty datových ovladačů a datových
zdrojů jako u aplikací založených na BDE. Nemůžeme použít komponentu databáze,
protože se nepřipojujeme k databázi. Také se nepoužívá komponenta sezení.
Hlavním rozdílem mezi Databázovými aplikacemi plochých
souborů a BDE databázovými aplikacemi je ve vytváření
datových množin a způsobu zavádění
a ukládání dat.
Můžeme také vytvořit hybridní aplikaci, pracující jako
jednovrstvová aplikace plochých souborů a po připojení k aplikačnímu serveru
pracuje jako klientská část vícevrstvové databázové aplikace. Tyto aplikace
používají
aktovkový model.
Vytváření datových množin
Protože databázové aplikace plochých souborů nepoužívají
existující databáze, jsou sami zodpovědné za vytváření datových množin.
Po vytvoření datové množiny je možno ji uložit do souboru. Při čtení pak
není nutno opětovně vytvářet tabulky, data jsou pouze zavedena ze souboru,
kde byla uložena. Indexy ale nejsou ukládány s tabulkou, je nutno je vždy
při zavedení tabulky vytvořit.
Když začínáme s Databázovou aplikací plochých souborů,
pak musíme nejprve vytvořit a uložit prázdné soubory pro naše datové množiny
před zahájením zápisu samotné aplikace. Tímto způsobem nemusíme definovat
metadata pro naše klientské datové množiny ve výsledné aplikaci.
Jak vytvoříme naše klientské datové množiny závisí na
tom, zda vytváříme novou datovou množinu nebo převádíme existující BDE
aplikaci.
Vytváření
nové datové množiny používající trvalé položky
Následující kroky popisují vytváření nové klientské datové
množiny pomocí Editoru položek:
-
Ze stránky MIDAS Palety komponent, přidáme komponentu
TClientDataSet
k naši aplikaci.
-
V místní nabídce klientské datové množiny zvolíme Fields
Editor. V místní nabídce Editoru položek zvolíme New Field a
popíšeme základní vlastnosti definice položky. Po vytvoření položky můžeme
tyto vlastnosti měnit v Inspektoru objektů. Pokračujeme v přidávání položek
dokud nemáme popsánu celou klientskou datovou množinu.
-
V místní nabídce klientské datové množiny zvolíme Create
DataSet. Tím vytvoříme prázdnou klientskou datovou množinu z trvalých
položek přidaných v Editoru položek.
-
V místní nabídce klientské datové množiny zvolíme Save
To File Tento příkaz není dostupný, dokud klientská datová množina
neobsahuje data.
-
V dialogovém okně ukládání souborů zvolíme jméno souboru
a uložíme kopii plochého souboru naší klientské datové množiny.
Poznámka: Můžeme také vytvořit klientskou datovou
množinu za běhu pomocí trvalých položek, které jsou uloženy s klientskou
datovou množinou. Pouze voláme metodu CreateDataSet.
Vytváření
datových množin pomocí definicí položek a indexů
Vytváření klientské datové množiny pomocí definic položek
a indexů se podobá použití komponenty TTable k vytvoření databázové
tabulky. Nespecifikujeme zde vlastnosti DatabeseName, TableName
a TableType, protože pro klientské datové množiny jsou zbytečné.
Nicméně jako u TTable použijeme vlastnost FieldDefs pro specifikaci
položek naší tabulky a vlastnost IndexDefs pro specifikaci indexů.
Po dokončení specifikace tabulky při návrhu zvolíme v místní nabídce klientské
datové množiny Create DataSet nebo za běhu aplikace voláme metodu
CreateDataSet.
Když pro naší klientskou aplikaci definujeme indexy,
pak dvě vlastnosti definice indexu aplikují unikátnost na klientskou datovou
množinu. Jedná se o TIndexDef::DescFields a TIndexDef::CaseInsFields.
DescFields definuje indexy, které řadí záznamy
podle některých položek vzestupně a podle jiných sestupně. Místo použítí
volby ixDescending k určení sestupného řazení podle všech položek
indexu, uvedeme jako hodnotu DescFields pouze ty položky, které
mají být sestupné. Např. když definujeme index, který řadí podle Field1,
pak podle Field2 a pak podle Field3 a nastavíme DescFields
na
Field1;Field3
pak výsledkem je, že řazení podle Field2 je vzestupné
a podle
Field1 a Field3 je sestupné.
CaseInsFields umožňuje definovat indexy umožňující
u některých položek indexu rozlišovat velikost písmen a u jiných ne. Místo
použití volby
isCaseInsensitive k nerozlišování velikosti písmen
u všech položek uvedeme ve vlastnosti CaseInsFields seznam pouze
těch položek u nichž velikost nechceme rozlišovat. Jedná se opět o seznam
jmen položek oddělovaný středníky.
Definice položek a indexů můžeme během návrhu vytvořit
pomocí Editoru. Pouze zvolíme příslušnou vlastnost v Inspektoru objektů
(FieldDefs nebo IndexDefs) a dvojitým kliknutím Editor zobrazíme.
Editor použijeme k přidávání, rušení a změnám definice. Vybereme definici
v Editoru a její vlastnosti můžeme editovat v Inspektoru objektů.
Můžeme také specifikovat definice indexů a položek kódem
za běhu. Např. následující kód vytváří a aktivuje klientskou datovou množinu
v obsluze události OnCreate formuláře:
void __fastcallTForm1::FormCreate(TObject
*Sender)
{
TFieldDef *pDef = ClientDataSet1->FieldDefs->AddFieldDef();
pDef->DataType = ftInteger;
pDef->Name = "Field1";
pDef = ClientDataSet1->FieldDefs->AddFieldDef();
pDef->DataType = ftString;
pDef->Size = 10;
pDef->Name = "Field2";
TIndexDef *pIndex = ClientDataSet1->IndexDefs->AddIndexDef();
pIndex->Fields = "Field1";
pIndex->Name = "IntIndex";
ClientDataSet1->CreateDataSet();
}
Vytvoření
datové množiny na základě existující tabulky
Pokud převádíme existující BDE aplikaci na jednovrstvovou
aplikaci plochých souborů, pak můžeme kopírovat existující tabulky a potom
je uložíme jako tabulky plochých souborů z IDE. Následující kroky popisují,
jak to udělat:
-
Ze stránky Data Access Palety komponent přidáme k
naší aplikaci komponentu
TTable. Nastavíme její vlastnosti DatabaseName
a TableName k identifikaci existující databázové tabulky. Nastavíme
její vlastnost
Active na
true.
-
Ze stránky MIDAS Palety komponent přidáme k aplikaci
komponentu
TClientDataSet.
-
V místní nabídce klientské datové množiny zvolíme Assign
Local Data. V zobrazeném dialogovém okně, zvolíme komponentu tabulky
přidanou v kroku 1 a stiskneme OK.
-
V místní nabídce klientské datové množiny zvolíme Save
To File. Tento příkaz není dostupný pokud klientská datová množina
neobsahuje data.
-
V dialogu ukládání souboru zvolíme jméno souboru a uložíme
kopii plochého souboru z naší databázové aplikace.
Zavádění a ukládání dat
V databázových aplikacích plochých souborů, všechny modifikace
na tabulkách existují pouze v deníku změn v paměti. Tento deník je udržován
odděleně od samotných dat i když je plně transparentní k objektům, které
používají klientskou datovou množinu. Tj. ovladače procházející klientskou
datovou množinou nebo zobrazující její data vidí pohled na data včetně
provedených změn. Pokud změny nechceme zrušit, pak změny můžeme sloučit
s daty voláním metody MergeChangeLog klientské datové množiny.
Po sloučení změn s daty klientské datové množiny, tato
data stále existují pouze v paměti. Změny tedy nejsou trvalé a ztratíme
je když uzavřeme klientskou datovou množinu a opět ji v naši aplikaci otevřeme,
nebo když ukončíme práci naší aplikace. Aby data se stala trvalými, musíme
je zapsat na disk. Změny na disk zapíšeme metodou SaveToFile. Tato
metoda přebírá jeden parametr, a to jméno vytvářeného (nebo přepisovaného)
souboru obsahujícího tabulku.
Když chceme přečíst tabulku dříve zapsanou pomocí metody
SaveToFile,
pak použijeme metodu LoadFromFile. LoadFromFile přebírá také
jeden parametr a to jméno souboru obsahujícího tabulku.
Když uložíme klientskou datovou množinu, pak metadata
popisující strukturu záznamů je uložena společně s datovou množinou, ale
bez popisu indexů. Z tohoto důvodu musíme přidat kód který opětovně vytvoří
indexy po zavedení dat ze souboru.
Pokud vždy zavádíme a ukládáme stejný soubor, pak můžeme
použít vlastnost
FileName místo metod LoadFromFile a SaveToFile.
Když vlastnost FileName je nastavena na přípustné jméno souboru,
pak data jsou automaticky zaváděna ze souboru, když klientskou datovou
množinu otevřeme a ukládána do souboru, když klientská datová množina je
uzavřena.
Podpora aktovkového modelu
Jednovrstvový model může být kombinován s více vrstvovým
modelem k vytvoření aplikace aktovkového modelu.
Poznámka: Aktovkový model se někdy nazývá rozpojitelný
model nebo model pro mobilní výpočty.
Když pracujeme v síti, pak aplikace aktovkového modelu
vypadá jako více vrstvový model: uživatel spustí klientskou aplikaci na
jednom počítači a připojí se prostřednictvím sítě na aplikační server na
vzdáleném počítači. Klient získá data z aplikačního serveru a zasílá na
něj aktualizace. Aktualizace jsou aplikovány aplikačním serverem do databáze,
která je sdílena s ostatními klienty organizace.
Předpokládejme dále, že databáze obsahuje data, které
naší prodejní reprezentanti mohou používat a aktualizovat. V tomto případě,
by bylo užitečné, kdyby prodejní reprezentanti mohli stáhnout nějaká nebo
všechna data z podnikové databáze a pracovat s nimi na svých přenosných
počítačích mimo podnik a po návratu do podniku se připojili k síti a provedené
aktualizace na existujících záznamech a nové záznamy byly přeneseny zpět
do podnikové databáze pro obecné použití. Tato možnost pracovat s odpojenými
daty a pozdější aplikování změn se nazývá aktovkový model.
Použitím aktovkového modelu můžeme převzít výhodu možností
komponenty klientské datové množiny číst a zapisovat data do plochých souborů,
které mohou být používány společně s aplikačním serverem.
K implementaci aktovkového modelu musíme:
-
Vytvořit více vrstvovou serverovou aplikaci.
-
Vytvořit jednovrstvovou databázovou aplikaci plochých souborů
jako naší klientskou aplikaci. Přidat komponentu připojení a nastavit vlastnost
RemoteServer
naši klientské datové množiny na specifikaci této komponenty připojení.
To umožní dotazovat se aplikačního serveru vytvořeného v kroku 1.
-
V klientské aplikaci se pokusíme připojit na aplikační server.
Pokud připojení je neúspěšné, pak se dotážeme uživatele zda pro práci používat
lokální kopii dat.
-
Do klientské aplikace přidáme kód aplikující aktualizace
na aplikační server.
Přechod na více vrstvové
aplikace
Ve dvouvrstvové aplikaci klient/server, aplikace je klientem
dotazujícím se přímo databázového serveru. Aplikace má dvě části: databázové
připojení a uživatelské rozhraní. K převedení dvouvrstvové aplikace klient/server
na vícevrstvovou aplikaci musíme:
-
Rozdělit existující aplikaci na aplikační server, který zpracovává
připojení k databázi a klientskou aplikaci, která obsahuje uživatelské
rozhraní.
-
Přidat rozhraní mezi klienta a aplikační server.
Je několik možností, jak to provést, ale následující sekvence
kroků zajistí minimum potřebné práce:
-
Vytvoříme nový projekt pro aplikační server, počínaje vzdáleným
modulem dat.
-
Duplikujeme část databázového připojení z naší dvouvrstvové
aplikace a pro každou datovou množinu a komponentu poskytovatele, vytvoříme
datové propojení mezi aplikačním serverem a klientem.
-
Z kopie naší dvouvrstvové aplikace odstraníme její přímé
databázové připojení a přidáme k ní potřebnou komponentu propojení.
-
Nahradíme v původním projektu každou datovou množinu BDE
klientskou datovou množinou.
-
Do klientské aplikace přidáme kód aplikující odložené aktualizace
na aplikační server.
-
Přesuneme komponenty datových množin do datového modulu aplikačního
serveru. Nastavíme vlastnost DataSet každého poskytovatele na specifikaci
odpovídající datové množiny.
Práce s daty
pomocí klientských datových množin
Jako u jiných datových množin, i klientskou datovou množinu
můžeme použít k předávání dat datovým ovladačům prostřednictvím komponenty
datového zdroje.
Protože TClientDataSet je potomkem TDataSet,
klientská datová množina dědí mnoho vlastností, metod a událostí definovaných
pro všechny komponenty datových množin.
Klientské datové množiny se liší od ostatních datových
množin v tom, že drží všechna data v paměti. Z tohoto důvodu, podpora obecných
databázových funkcí musí být rozšířena o další možnosti a funkce. Některé
z těchto funkcí a rozdílů zavedených klientskými datovými množinami jsou
popsány v následujících bodech:
Procházení daty
Pokud aplikace používá standardní datové ovladače, pak uživatel
může procházet záznamy klientské datové množiny stejně jako v jiných datových
množinách. Záznamy můžeme také procházet programově pomocí standardních
metod datových množin jako je First, GotoKey, Last,
Next
a
Prior.
Klientské datové množiny také podporují možnosti standardních
záložek pro označování a přechod na specifikovaný záznam.
Narozdíl od většiny datových množin, klientské datové
množiny mohou také umisťovat kurzor na specifikovaný záznam v datové množině
pomocí vlastnosti
RecNo. Normálně aplikace používá RecNo
k určení čísla záznamu současného záznamu. Klientská datová množina může
také nastavit RecNo na číslo jistého záznamu a udělat tak tento
záznam současným.
Omezování záznamů
K omezení uživatele na podmnožinu dostupných dat, aplikace
může použít rozsahy a filtry. Když aplikujeme rozsah nebo filtr, pak klientská
datová množina nezobrazuje všechna data z paměti. Jsou zobrazována pouze
ta data, která splňují podmínku rozsahu nebo filtru.
Pro většinu datových množin, řetězec filtru je rozkládán
na příkazy SQL a ty jsou pak prováděny na databázovém serveru. Klientské
datové množiny mají svoji vlastní podporu filtrů, která zahrnuje většinu
operací ostatních datových množin. Např. když použijeme klientskou datovou
množinu, pak výraz filtru může obsahovat řetězcové operátory, které vracejí
podřetězce, operátory rozkládající časové nebo datumové hodnoty a mnoho
dalších. Klientské datové množiny mohou také filtrovat položky BLOB nebo
položky ADT a položková pole.
Když aplikujeme rozsah nebo filtr, klientská datová množina
stále ukládá všechny své záznamy v paměti. Rozsah nebo filtr pouze určuje,
které záznamy jsou dostupné ovladači pro procházení a zobrazování dat z
klientské datové množiny. Ve více vrstvových aplikacích, můžeme také omezit
data uložená v klientských datových množinách na podmnožinu záznamů předáním
parametru aplikačnímu serveru.
Podpora vzájemného
vztahu Master-detail
Stejně jako tabulky, i klientské datové množiny podporují
vztah Master-detail. Když nastavíme vzájemný vztah Master-detail, pak propojíme
dvě datové množiny tak, že všechny záznamy z jedné (detail) vždy odpovídají
jednomu současnému záznamu v druhé (master).
Dále můžeme nastavit vzájemný vztah Master-detail v klientských
datových množinách pomocí vnořených tabulek. Můžeme to provést jedním ze
dvou způsobů:
-
Získání záznamů obsažených ve vnořené množině od komponenty
poskytovatele. Když komponenta poskytovatele reprezentuje tabulku Master
vzájemného vztahu Master-detail, pak je automaticky vytvořena položka vnořené
datové množiny reprezentující tabulku detail pro každý záznam.
-
Definování vnořeného detailu pomocí Editoru položek. Při
návrhu v místní nabídce klientské datové množiny zvolíme Fields Editor.
Volbou Add Fields v místní nabídce editoru přidáme novou trvalou
položku. Typ nové položky nastavíme na DataSet. V Editoru položek
pak definujeme strukturu naší detailní tabulky.
Když naše klientská datová množina obsahuje vnořenou detailní
datovou množinu, pak TDBGrid poskytuje podporu pro zobrazování vnořeného
detailu v zobrazeném okně. Můžeme také zobrazovat a editovat tyto datové
množiny v datových ovladačích pomocí oddělené klientské datové množiny
pro detailní množinu. Při návrhu, vytvoříme trvalé položky pro položky
v naši klientské datové množině včetně položky DataSet pro vnořenou
detailní množinu.
Nyní můžeme vytvořit klientskou datovou množinu k reprezentaci
vnořené detailní množiny. Nastavíme vlastnost DataSetField této
klientské datové množiny na trvalou položku DataSet v datové množině
Master.
Ve více vrstvových aplikacích, používání vnořené detailní
množiny je nutné, pokud chceme aplikovat aktualizace z tabulek Master a
Detail na aplikační server. V databázových aplikacích plochých souborů,
použití vnořené detailní množiny umožňuje ukládat detaily se záznamy Master
do jednoho plochého souboru, namísto zavádění dvou samostatných datových
množin a opětovného vytváření indexů pro vytvoření vzájemného vztahu.
Poznámka: K použití vnořené detailní množiny,
vlastnost ObjectView klientské datové množiny musí být true.
Omezení datových hodnot
Klientské datové množiny poskytují podporu pro datová omezení.
Vždy jsou podporována přizpůsobená omezení. To umožňuje poskytovat vlastní,
aplikací definované omezení hodnot uživatelem odesílaných do klientské
datové množiny.
Dále, pokud používáme komponentu poskytovatele pro komunikaci
se vzdáleným databázovým serverem, poskytovatel má volby předávající omezení
serveru klientské datové množině.
Ve vícevrstvových aplikacích, mohou být okamžiky, kdy
potřebujeme datová omezení vypnout, a to obzvláště když klientská datová
množina neobsahuje všechny záznamy z odpovídající datové množiny na aplikačním
serveru.
Zpřístupnění dat pouze pro čtení
TDataSet zavádí vlastnost CanModify, kterou
aplikace může určovat, zda data v datové množině mohou být editována. Aplikace
nemůže vlastnost CanModify změnit, protože pro některé potomky TDataSet,
připojená databáze a ne aplikace, určuje zda data mohou být modifikovány.
Protože klientská datová množina reprezentuje data v
paměti, naše aplikace může vždy řídit, zda uživatel může editovat tato
data. Pro zabránění uživatele v editaci dat, nastavíme vlastnost ReadOnly
klientské datové množiny na true. Tímto nastavením také nastavíme
vlastnost CanModify na false.
Na rozdíl od ostatních typů datových množin, klientskou
datovou množinu nemusíme uzavřít, když chceme změnit jeho možnost zápisu.
Aplikace může kdykoliv změnit současný stav možnosti zápisu nastavením
vlastnosti
ReadOnly.
Editace dat
Klientská datová množina reprezentuje svá data jako paket
dat v paměti. Tento paket je hodnota vlastnosti Data klientské datové
množiny. Implicitně ale editace nejsou ukládány ve vlastnosti Data.
Vkládání, rušení a modifikace (provedené uživatelem nebo programově) jsou
ukládány v interním deníku změn, reprezentovaným vlastností Delta.
Deník změn slouží ke dvěma účelům:
-
Když pracujeme s poskytovatelem, pak deník změn je požadován
mechanismem pro aplikování aktualizací na aplikační server.
-
V libovolné aplikaci, deník změn poskytuje sofistikovanou
podporu pro rušení změn.
Vlastnost LogChanges povoluje zakázat zaznamenávání
změn do deníku. Když LogChanges je true, pak změny jsou do
deníku zaznamenávány. Když LogChanges je false, pak změny
jsou přímo promítnuty do vlastnosti Data. Můžeme tedy deník změn
zakázat pro jednovrstvové aplikace, pokud nepotřebujeme podporu pro rušení
změn.
Editace v deníku změn zůstávají, pokud nejsou odstraněny
aplikací. Aplikace odstraňuje editace z deníku při:
Poznámka: Ukládání klientské datové množiny do
souboru neodstraňuje editace z deníku změn. Když opětovně zavedeme datovou
množinu, pak vlastnosti
Data a Delta jsou stejné jako když
data byla uložena.
Odvolání změn
Přestože původní verze záznamů zůstává ve vlastnosti Data
nezměněna, po opuštění a opětovném návratu na editovaný záznam, uživatel
vidí poslední změněnou verzi záznamu. Pokud uživatel nebo aplikace edituje
záznam několikrát, pak každá změněná verze záznamu je uložena do deníku
změn jako samostatná položka.
Ukládání každé změny umožňuje podporu více úrovní operací
undo
k obnovení předchozího stavu záznamu.
K odstranění poslední změny na záznamu voláme UndoLastChange.
UndoLastChange
přebírá logický parametr FollowChange, který indikuje zda kurzor
přesunout na obnovený záznam (true) nebo ponechat kurzor na současném
záznamu (false). Pokud je několik změn na jednom záznamu, pak každé
volání UndoLastChange odstraňuje poslední vrstvu editace. UndoLastChange
vrací logickou hodnotu indikující úspěch odstranění změny. Vlastnost ChangeCount
slouží k určení zda je ještě více změn ke zrušení. ChangeCount určuje
počet změn uložených do deníku změn.
Místo odstraňování jednotlivých vrstev změn na jednom
záznamu, můžeme je všechny odstranit najednou. K odstranění všech změn
záznamu, vybereme záznam a voláme RevertRecord. RevertRecord
odstraňuje všechny změny současného záznamu z deníku změn.
Kdykoliv v průběhu editace můžeme uložit současný stav
deníku změn pomocí vlastnosti SavePoint. Přečtením SavePoint
navrátíme označovač na současnou pozici v deníku změn. Později, pokud chceme
zrušit všechny změny od přečteného bodu uložení, pak nastavíme SavePoint
na předem přečtenou hodnotu. Naše aplikace může získat hodnoty pro více
bodů uložení. Pokud se přesuneme zpět v deníku změn na bod uložení, pak
hodnoty všech následujících bodů uložení jsou chybné.
Všechny změny uložené v deníku změn můžeme zrušit voláním
CancelUpdates.
CancelUpdates
vyprazdňuje deník změn, čímž efektivně zrušíme všechny editace všech záznamů.
Při volání CancelUpdates musíme být opatrní. Po volání CancelUpdates
nelze obnovit žádnou změnu z deníku.
Uložení změn
Klientské datové množiny používají různé mechanismy pro převzetí
změn z deníku změn, v závislosti na tom, zda jsou použity v samostatné
aplikaci nebo reprezentují data se vzdáleného aplikačního serveru. Bez
ohledu na použitý mechanismus, deník změn je automaticky vyprázdněn po
převzetí všech změn.
Samostatné aplikace mohou jednoduše slučovat změny do
lokální vyrovnávací paměti reprezentované vlastností Data. Není
nutno se zabývat řešením konfliktů se změnami provedenými jinými uživateli.
Pro sloučení deníku změn do vlastnosti Data voláme metodu MergeChangeLog.
Metodu MergeChangeLog nemůžeme použít ve více
vrstvových aplikacích. Aplikační server potřebuje informace z deníku změn
aby mohl rozpustit aktualizované záznamy v datech uložených v databázi.
Voláme ApplyUpdates, která zasílá změny na aplikační server a aktualizuje
vlastnost Data pouze tehdy, když modifikace byly úspěšně odeslány
do databáze.
Řazení a indexování
Používání indexů poskytuje několik výhod našim aplikacím:
-
Umožňují klientským datovým množinám rychlou lokalizaci dat.
-
Umožňují naši aplikaci nastavit vzájemný vztah mezi klientskými
datovými množinami, jako jsou vyhledávací tabulky nebo vztah Master-detail.
-
Určují pořadí zobrazování záznamů.
Pokud klientská datová množina je použita ve více vrstvové
aplikaci, pak zdědí implicitní index a řadící pořadí od dat získaných z
aplikačního serveru. Implicitní index se nazývá DEFAULT_ORDER. Toto
pořadí můžeme použít, ale nemůžeme změnit nebo zrušit index.
Mimo implicitního indexu, klientská datová množina udržuje
sekundární index, nazvaný CHANGEINDEX, na změněných záznamech uložených
v deníku změn (vlastnost Delta). CHANGEINDEX řadí všechny
záznamy v klientské datové množině jak budou zobrazeny, pokud změny specifikované
v Delta budou aplikovány. CHANGEINDEX je založen na pořadí
zděděném od DEFAULT_ORDER. CHANGEINDEX nelze také změnit
nebo zrušit.
Můžeme používat ostatní existující indexy pro datovou
množinu a můžeme vytvářet své vlastní indexy. V následujících bodech je
popsáno jak vytvářet a používat indexy v klientských datových množinách:
Přidávání nových indexů
K vytvoření nového indexu pro klientskou datovou množinu
voláme AddIndex.
AddIndex umožňuje specifikovat vlastnosti
indexu včetně:
-
Jména indexu. Jméno může být použito k přepínání indexů za
běhu.
-
Položek tvořících index. Index použije tyto položky k seřazení
záznamů a k umístění záznamů, které mají v těchto položkách specifické
hodnoty.
-
Jak index řadí záznamy. Implicitně, indexy používají vzestupné
pořadí. Implicitně je rozlišována velikost písmen. Různými volbami lze
toto změnit.
-
Implicitní úroveň seskupování pro index.
Tip: Indexovat a řadit můžeme v klientských datových
množinách, i na interních počitatelných položkách.
Vytvořené indexy jsou řazeny ve vzestupném abecedním
pořadí závisejícím na národnostním nastavení počítače. V parametru voleb
indexu můžeme přidat
ixDescending k nastavení volby přepisující
implicitní nastavení.
Poznámka: Když vytváříme indexy ve stejné době
jako klientská datová množina, pak můžeme vytvořit indexy, které řadí ve
vzestupném pořadí na některých položkách a sestupné řazení na jiných.
Řazení řetězcových položek v indexech implicitně rozlišuje
velikost písmen. V parametru voleb indexu můžeme přidat ixCaseInsensitive
k ignorování velikosti písmen při řazení.
Poznámka: Když vytváříme indexy ve stejné době
jako klientská datová množina, pak můžeme vytvářet indexy, které v některých
položkách rozlišují velikost písmen a v jiných ne.
Varování: Indexy přidané pomocí AddIndex
nejsou ukládány při ukládání klientské datové množiny do souboru.
Rušení a přepínání indexů
K odstranění námi vytvořených indexů pro klientskou datovou
množinu, voláme
DeleteIndex a specifikujeme jméno odstraňovaného
indexu. Indexy
DEFAULT_ORDER a CHANGEINDEX nelze odstranit.
K použití různých indexů s klientskou datovou množinou,
když je dostupných více indexů, použijeme vlastnost IndexName k
výběru používaného indexu. Během návrhu, můžeme vybírat z dostupných indexů
v rozbalovacím seznamu vlastnosti IndexName v Inspektoru objektů.
Používání indexů k seskupování
dat
Když v naší klientské datové množině použijeme index, určíme
tím automaticky řadící pořadí záznamů. Seřazené záznamy obvykle obsahují
duplicitní hodnoty na položkách tvořících index. Např. předpokládejme následující
část tabulky objednávek, která je indexována na položkách SalesRep
a Customer:
SalesRep |
Customer |
OrderNo |
Amount |
1 |
1 |
5 |
100 |
1 |
1 |
2 |
50 |
1 |
2 |
3 |
200 |
1 |
2 |
6 |
75 |
2 |
1 |
1 |
10 |
2 |
3 |
4 |
200 |
Vidíme, že hodnoty ve sloupci SalesRep se opakují.
V záznamech pro SalesRep čísla 1, se opakují hodnoty ve sloupci
Customer.
Tedy data lze seskupit podle SalesRep a ve skupině
SalesRep
je můžeme seskupit podle Customer. Každé seskupování má přiřazenou
úroveň. V našem případě, skupina SalesRep má úroveň 1 (protože není
vnořena do žádné jiné skupiny) a skupina Customer má úroveň 2 (protože
je vnořena ve skupině úrovně 1). Úroveň seskupování odpovídá pořadí položek
v indexu. Když vytváříme index, pak můžeme specifikovat podporované úrovně
seskupování (až do počtu položek v indexu).
Klientské datové množiny umožňují určit, kde současný
záznam se v dané seskupovací úrovni nachází. To umožňuje naší aplikaci
zobrazovat záznamy různě, a to podle toho, zda se jedná o první záznam
skupiny, prostřední záznam skupiny nebo poslední záznam skupiny. Např.
můžeme chtít zobrazovat opakující se hodnoty pouze v prvním záznamu skupiny.
Pokud to provedeme pro předchozí tabulku, pak získáme:
SalesRep |
Customer |
OrderNo |
Amount |
1 |
1 |
5 |
100 |
|
|
2 |
50 |
|
2 |
3 |
200 |
|
|
6 |
75 |
2 |
1 |
1 |
10 |
|
3 |
4 |
200 |
K určení, kde ve skupině se nachází současný záznam, používáme
metodu
GetGroupState.
GetGroupState přebírá celé číslo určující
úroveň seskupování a vrací hodnotu indikující, kde se ve skupině nachází
současný záznam.
Indexování za běhu
Místo vytváření indexů, které se stanou částí klientské datové
množiny, můžeme vytvářet dočasné indexy za běhu specifikací položek použitých
pro indexování ve vlastnosti IndexFieldNames. Jména položek oddělujeme
středníky. Pořadí jmen položek v seznamu je významné.
Poznámka: Při tomto způsobu indexování nelze
určit sestupné řazení a nerozlišování velikosti písmen. Také zde není podpora
pro seskupování.
Reprezentace počitatelných
hodnot
Jako v jiných datových množinách i v klientských datových
množinách lze používat počitatelné položky. Jsou to položky jejichž hodnoty
jsou počítány dynamicky, obvykle na základě hodnot ostatních položek ve
stejném záznamu. Klientské datové množiny umožňují optimalizaci počitatelných
položek použitím
interních počitatelných položek.
Můžeme také říci klientským datovým množinám, aby vytvářely
počitatelné hodnoty, které sumarizují data z několika záznamů pomocí udržovaných
agregátů.
Používání interních
počitatelných položek v klientských datových množinách
V ostatních datových množinách, naše aplikace musí vypočítat
hodnoty počitatelných položek pokaždé, když se změní záznam nebo uživatel
edituje nějakou položku v současném záznamu. Provádí to obsluha události
OnCalcFields.
I když toto je možno stále používat, klientské datové
množiny minimalizují počet přepočítávaných počitatelných položek ukládáním
vypočítaných hodnot do klientské datové množiny. I když tyto hodnoty jsou
ukládány s klientskou datovou množinou, je stále zapotřebí přepočítávat
hodnoty, když uživatel edituje současný záznam, ale aplikace již nepotřebuje
provádět přepočítávání při změně současného záznamu. K uložení vypočítaných
hodnot do dat klientské datové množiny, používáme místo počitatelných položek
interní počitatelné položky.
Interní počitatelné položky, stejně jako počitatelné
položky, jsou vypočítávány v obsluze události OnCalcFields. Můžeme
ale optimalizovat obsluhu události testováním vlastnosti State naší
klientské datové množiny. Když stav je dsInternalCalc, pak interní
počitatelné položky musíme přepočítat. Při stavu dsCalcFields musíme
přepočítat normální počitatelné položky.
K používání interních počitatelných položek, musíme definovat
položky jako interně počitatelné dříve než vytvoříme klientskou datovou
množinu. Pokud vytváříme klientskou datovou množinu používající trvalé
položky, definujeme položky jako interně počitatelné výběrem InternalCalc
v Editoru položek. Když vytváříme klientskou datovou množinu pomocí definic
položek, pak nastavíme vlastnost InternalCalcField odpovídající
definice položky na true.
Poznámka: Ostatní typy datových množin používají
interní počitatelné položky. Nicméně s ostatními datovými množinami, tyto
hodnoty nepřepočítáváme v obsluze události OnCalcFields. Jsou počítány
automaticky BDE nebo vzdáleným databázovým serverem.
Používání udržovaných agregátů
Klientské datové množiny poskytují podporu pro sumarizaci
dat nad skupinami záznamů. Protože tyto sumarizace jsou automaticky aktualizovány
při editaci dat v datové množině, jsou tato sumarizovaná data nazývána
udržované
agregáty.
Ve své nejjednodušší formě, udržované agregáty umožňují
získávat informace typu součet všech hodnot ve sloupci klientské datové
množiny. Jsou flexibilní, ale pro podporu různých součtových výpočtů a
k poskytnutí mezisoučtů pro skupiny záznamů definujeme položky v indexu,
které podporují seskupování.
Následující body popisují jak to provést:
Specifikování
agregátů
Ke specifikaci, co chceme v klientské datové množině
nad záznamy sumarizovat, použijeme vlastnost Aggregates. Aggregates
je kolekce agregačních specifikací (TAggregate). Můžeme přidávat
agregační specifikátory k naší klientské datové množině pomocí Editoru
položek při návrhu, nebo pomocí metody Add vlastnosti Aggregates
za běhu. Pokud chceme vytvořit položkovou komponentu pro agregáty, vytvoříme
trvalou položku pro agregované hodnoty v Editoru položek.
Poznámka: Když vytváříme agregované položky,
pak příslušné agregované objekty jsou přidány k vlastnosti Aggregates
klientské datové množiny automaticky.
Pro každý agregát, vlastnost Expression indikuje
jaký výpočet jej reprezentuje. Expression může obsahovat jednoduchý
součtový výraz jako
Sum(Field1)
nebo složitější výraz, kombinující informace z několika
položek, jako
Sum(Qty * Price) - Sum(AmountPaid)
Agregační výrazy zahrnují jeden nebo více sumárních operátorů
z následující tabulky:
Operátor |
Použití |
Sum |
Součet hodnot pro numerickou položku nebo výraz. |
Avg |
Výpočet průměrné hodnoty pro číselné, datumově časové
položky nebo výrazy. |
Count |
Specifikuje počet neprázdných hodnot pro položku nebo
výraz. |
Min |
Indikuje minimální hodnotu pro řetězcovou, číselnou nebo
datumovo časovou položku nebo výraz. |
Max |
Indikuje maximální hodnotu pro řetězcovou, číselnou nebo
datumovo časovou položku nebo výraz. |
Sumární operátory pracují na hodnotách položek nebo výrazech
vytvořených z hodnot položek pomocí stejných operátorů jako používáme pro
vytváření filtrů. Sumární operátory ale nelze vnořovat. Můžeme vytvořit
výraz používající operátory na sumarizovaných hodnotách s jinou sumarizovanou
hodnotou nebo na sumarizované hodnotě a konstantě. Nelze ale kombinovat
sumarizované hodnoty s hodnotami položek. Tato pravidla jsou použita v
následujících výrazech:
Sum(Qty * Price) |
povoleno - součet výrazů na položkách |
Max(Field1) - Max(Field2) |
povoleno - výraz na sumarizovaných hodnotách |
Avg(DiscountRate) * 100 |
povoleno - výraz sumarizované hodnoty a konstanty |
Min(Sum(Field1)) |
nepovoleno - vnořené sumarizované hodnoty |
Count(Field1) - Field2 |
nepovoleno - výraz sumární hodnoty a položky |
Agregování
nad skupinami záznamů
Implicitně, udržované agregáty jsou vypočítávány tak,
že sumarizují všechny záznamy v klientské datové množině. Nicméně můžeme
specifikovat, že chceme sumarizovat nad záznamy ve skupinách. To umožňuje
poskytnout bezprostřední sumarizace jako jsou mezisoučty pro skupiny záznamů,
které sdílejí společné hodnoty položky.
Dříve než můžeme specifikovat udržovaný agregát nad skupinami
záznamů, musíme použít index, který podporuje potřebné seskupování. Když
již máme index, který seskupuje potřebným způsobem data, pak specifikujeme
vlastnosti
IndexName a GroupingLevel agregátu k indikaci,
který index použít a která skupina nebo podskupina na tomto indexu definuje
seskupování záznamů.
Např. předpokládejme následující část z tabulky objednávek,
která je seskupena podle SalesRep a v SalesRep podle Customer:
SalesRep |
Customer |
OrderNo |
Amount |
1 |
1 |
5 |
100 |
1 |
1 |
2 |
50 |
1 |
2 |
3 |
200 |
1 |
2 |
6 |
75 |
2 |
1 |
1 |
10 |
2 |
3 |
4 |
200 |
Následující kód nastavuje udržovaný agregát, který indikuje
celková množství pro každého prodejního reprezentanta:
Agg->Expression = "Sum(Amount)";
Agg->IndexName = "SalesCust";
Agg->GroupingLevel = 1;
Agg->AggregateName = "Total for Rep";
Pro přidání agregátu, který sumarizuje pro každého zákazníka
daného prodejního reprezentanta, vytvoříme udržovaný agregát s úrovní 2.
Udržované agregáty, které sumarizují nad skupinami záznamů
jsou přiřazeny k jistému indexu. Vlastnost Aggregates může obsahovat
agregáty, které používají různé indexy. Nicméně, pouze agregáty, které
sumarizují nad celou datovou množinou a ty, které používají současný index
jsou přípustné. Změnou současného indexu se změní přípustné agregáty. K
určení, které agregáty jsou přípustné v daný čas použijeme vlastnost ActiveAggs.
Získávání
agregovaných hodnot
K získání hodnot udržovaných agregátů, voláme metodu
Value
objektu
TAggregate, který reprezentuje agregát. Vrácená hodnota
udržovaného agregátu je pro skupinu, která obsahuje současný záznam klientské
datové množiny.
Když sumarizujeme nad celou klientskou datovou množinou,
pak můžeme volat Value kdykoliv k získání udržovaného agregátu.
Pokud ale sumarizujeme nad seskupenými informacemi, pak musíme být opatrní
aby současný záznam byl ve skupině, jejíž sumarizaci chceme získat. Z tohoto
důvodu je dobrou myšlenkou získat agregované hodnoty v přesně definovaných
okamžicích, jako např. když se přesuneme na první záznam skupiny nebo při
přesunu na poslední záznam skupiny. K určení, kde se současný záznam nachází
ve skupině používáme metodu GetGroupState.
K zobrazení udržovaných agregátů v datových ovladačích,
použijeme Editor položek k vytvoření trvalé agregované položkové komponenty.
Když specifikujeme agregovanou položku v Editoru položek, pak Aggregates
klientské datové množiny je automaticky aktualizován vložením příslušné
agregační specifikace. Vlastnost AggFields obsahuje novou agregovanou
položkovou komponentu a metoda FindField ji vrací.
Přidávání
informací specifických pro aplikaci k datům
Vývojář aplikace, může přidat k vlastnosti Data klientské
datové množiny, své informace. Protože tyto informace tvoří s ostatními
daty paket, jsou také obsaženy, když ukládáme data do souboru nebo do proudu.
Jsou také kopírovány, když kopírujeme data do jiné datové množiny. Nepovinně
mohou být i vkládány do vlastnosti Delta a tak aplikační server
může tyto informace číst, když získává aktualizace od klientů.
K uložení informací specifických pro aplikaci do vlastnosti
Data,
použijeme metodu SetOptionalParam. Tato metoda ukládá
OleVariant,
který obsahuje data pod specifikovaným jménem.
K získání těchto informací použijeme metodu GetOptionalParam
s předáním jména pod kterým jsou informace uloženy.
Kopírování dat z jiné
datové množiny
Pro kopírování dat z jiné datové množiny při návrhu, v místní
nabídce klientské datové množiny zvolíme Assign Local Data. Zobrazený
dialog uvádí seznam všech dostupných datových množin v projektu. Vybereme
jednu, ze které chceme kopírovat a stiskneme OK. Když kopírujeme
zdrojovou datovou množinu, pak naše klientská datová množina je automaticky
aktivována.
Pro kopírování z jiné datové množiny za běhu, můžeme
přiřazovat
její data přímo nebo, pokud zdrojem je jiná klientská datová množina,
pak můžeme kurzor
klonovat.
Přímé přiřazení dat
Můžeme použít vlastnost Data klientské datové množiny
k přiřazení dat klientské datové množině z jiné datové množiny. Data
je OleVariant ve tvaru paketu dat. Datový paket můžeme získat z
jiné klientské datové množiny, nebo z libovolné jiné datové množiny pomocí
poskytovatele. Když datový paket je přiřazen vlastnosti Data, jeho
obsah je automaticky zobrazován v datových ovladačích připojených ke klientské
datové množině prostřednictvím komponenty datového zdroje.
Když otevřeme klientskou datovou množinu, která používá
komponentu poskytovatele, pak datové pakety jsou automaticky přiřazeny
vlastnosti
Data.
Když naše klientská množina nepoužívá poskytovatele,
pak můžeme kopírovat data z jiné klientské datové množiny takto:
ClientDataSet1->Data = ClientDataSet2->Data;
Poznámka: Když kopírujeme vlastnost Data
jiné klientské datové množiny, pak také kopírujeme deník změn, ale nekopírujeme
rozsahy nebo filtry, které mohly být aplikovány. K vložení filtrů a rozsahů,
musíme klonovat kurzor zdrojové datové množiny.
Pokud chceme přiřadit data z datové množiny podporující
BDE, pak můžeme použít její vlastnost Provider ke kopírování dat
bez nutnosti přidání komponenty poskytovatele:
ClientDataSet1->Data = Table1->Provider->Data;
Pokud kopírujeme z přizpůsobené datové množiny, pak můžeme
vytvořit komponentu poskytovatele datové množiny, připojit ji k zdrojové
datové množině a pak kopírovat její data:
TempProvider = new TDataSetProvider(Form1);
TempProvider->DataSet = SourceDataSet; //
SourceDataSet je přizpůsobená datová množina
ClientDataSet1->Data = TempProvider->Data;
delete TempProvider;
Poznámka: Když přímo přiřadíme vlastnost Data,
pak nový paket dat není sloučen s existujícími daty. Všechna předchozí
data jsou nahrazena.
Pokud chceme sloučit změny z jiné datové množiny (místo
kopírování jejich dat), pak musíme použít komponentu poskytovatele.
Klonování kurzoru
klientské datové množiny
TClientDataSet poskytuje proceduru CloneCursor
k umožnění práce s druhým pohledem na specifikovanou klientskou datovou
množinu za běhu. CloneCursor umožňuje druhé klientské datové množině
sdílet data původní klientské datové množiny. Je to výhodnější než kopírování
všech původních dat, ale protože data jsou sdílena, druhá klientská datová
množina nemůže modifikovat data bez ovlivnění původní klientské datové
množiny.
CloneCursor přebírá tři parametry: Source
specifikuje klonovanou klientskou datovou množinu. Poslední dva parametry
(Reset a KeepSetting) indikují zda kopírovat i jiné informace
než data. Tyto informace zahrnují filtry, současný index, spojení s tabulkou
Master (když zdrojová datová množina je tabulkou Detail), vlastnost ReadOnly
a libovolná spojení na připojovací komponentu nebo rozhraní poskytovatele.
Když Reset a KeepSetting jsou false,
klonovaná klientská datová množina je otevřena a nastavení zdrojové klientské
datové množiny jsou použity k nastavení vlastností cíle. Když Reset
je
true, pak vlastnosti cílové datové množiny získají své implicitní
hodnoty (není filtr nebo index, není tabulka Master, ReadOnly je
false
a nejsou specifikovány komponenty připojení nebo poskytovatele). Když KeepSettings
je true, pak vlastnosti cílové datové množiny se nemění.
Používání klientské
datové množiny s poskytovatelem dat
Když používáme klientskou datovou množinu ve více vrstvových
aplikacích, pak klientská datová množina používá rozhraní IProvider
k získání dat z aplikačního serveru a po editaci dat, které je lokální,
jsou aktualizace aplikovány na vzdálenou databázi.
Tento proces popisují následující body:
Specifikování poskytovatele
dat
Dříve než klientská datová množina může získávat data z a
aplikovat aktualizace na aplikační server, musí získat rozhraní IProvider.
Jednovrstvová aplikace a klientské aplikace používající aktovkový model
nemají rozhraní
IProvider definováno. Ve více vrstvových aplikacích,
obvykle používáme vlasnosti
RemoteServer a ProviderName k
výběru rozhraní poskytovatele z dostupných rozhraní v klientské aplikaci.
RemoteServer specifikuje jméno komponenty připojení
ve které získáme seznam poskytovatelů. Komponenta připojení sídlí ve stejném
datovém modulu jako klientská datová množina. Zřizuje a udržuje připojení
na aplikační server, někdy nazývaný Datový agent (data broker).
Při návrhu (po specifikaci RemoteServer), můžeme
vybrat poskytovatele v rozbalovacím seznamu vlastnosti ProviderName
v Inspektoru objektů. Za běhu můžeme přepínat mezi dostupnými poskytovateli
nastavením vlastnosti
ProviderName kódem.
Předávání parametrů
na aplikační server
Klientské datové množiny mohou předávat parametry na aplikační
server ke specifikaci, která data chceme poskytovat v zasílaných datových
paketech. Tyto parametry mohou specifikovat:
Hodnoty parametrů, které naše klientská datová množina zasílá
na aplikační server, můžeme specifikovat při návrhu nebo za běhu. Při návrhu,
vybereme klientskou datovou množinu a dvojitě klikneme na vlastnost Params
v Inspektoru objektů. Tím vyvoláme Editor parametrů, kde můžeme přidávat,
rušit a přesouvat parametry. Výběrem parametru v tomto Editoru se parametr
zobrazí v Inspektoru objektů, kde můžeme editovat jeho vlastnosti.
Za běhu použijeme metodu CreateParam vlastnosti
Params
k přidávání parametrů k naší klientské datové množině. CreateParam
vrací objekt parametru daný specifikovaným jménem, typem parametru a datovým
typem. Pak můžeme použít vlastnosti parametru objektu k přiřazení hodnoty
parametru.
Např. následující kód nastavuje hodnotu parametru nazvaného
CustNo
na 605:
TParam *pParam=ClientDataSet1->Params->CreateParam(ftInteger,"CustNo",
ptInput);
pParam->AsInteger = 605;
Pokud klientská datová množina není aktivní, pak můžeme
zaslat parametry na aplikační server a získat datový paket, který zohledňuje
hodnoty těchto parametru, jednoduchým nastavením vlastnosti Active
na true.
Pokud klientská datová množina je již aktivní, pak můžeme
použít metodu
SendParams k zaslání hodnot parametrů na aplikační
server. Pak musíme explicitně požadovat další data z aplikačního serveru.
Aplikační server opětovně spustí dotaz nebo uloženou proceduru pomocí nových
hodnot parametrů a pak začne poskytovat data počínaje prvním záznamem v
nové výsledkové množině.
Poznámka: Můžeme chtít inicializovat hodnoty
parametrů od současného nastavení na aplikačním serveru. Provedeme to volbou
Fetch
Params v místní nabídce klientské datové množiny při návrhu nebo voláním
metody
FetchParams za běhu.
Zasílání parametrů
dotazů a uložených procedur
Když poskytovatel na aplikačním serveru reprezentuje výsledek
dotazu nebo uložené procedury, pak můžeme použit vlastnost Params
ke specifikaci hodnot parametrů. Klientská datová množina předává tyto
parametry na aplikační server, kde jsou přiřazeny k dotazu nebo uložené
proceduře patřící k poskytovateli.
Poznámka: Jména parametrů se musí shodovat
se jmény odpovídajících parametrů komponent TQuery nebo TStoredProc
na aplikačním serveru.
Omezování záznamů parametry
Když poskytovatel na aplikačním serveru reprezentuje výsledek
komponenty tabulky, pak můžeme použít vlastnost Params k omezení
záznamů, které jsou poskytnuty vlastnosti Data.
Každé jméno parametru se musí shodovat se jménem položky
v komponentě
TTable na aplikačním serveru. Komponenta poskytovatele
na aplikačním serveru zasílá pouze ty záznamy, jejichž hodnoty na odpovídajících
položkách se shodují s hodnotami přiřazenými parametrům.
Např. předpokládejme klientskou aplikaci, která zobrazuje
objednávky jednoho zákazníka. Když uživatel identifikuje zákazníka, pak
klientská datová množina zasílá jeden parametr (např. jména CustID)
jehož hodnota identifikuje zákazníka jehož objednávky chceme zobrazit.
Aplikační server pak zašle pouze ty záznamy, které se týkají požadovaného
zákazníka. Je to mnohem efektivnější než získání všech záznamů objednávek
od aplikačního serveru a filtrování záznamů na straně klienta.
Požadování dat z aplikačního
serveru
Dvě vlastnosti a tři metody TClientDataSet určují
způsob získávání dat z aplikačního serveru ve více vrstvových aplikacích:
Vlastnost nebo metoda |
Význam |
Vlastnost FetchOnDemand |
Určuje zda klientská datová množina automaticky získá
potřebná data nebo zde je bude muset získávat funkcemi GetNextPacket,
FetchBlobs
a FetchDetails. |
Vlastnost PacketRecords |
Specifikuje typ nebo počet záznamů vracených v každém
paketu dat. |
Metoda GetNextPacket |
Získává následující paket dat z aplikačního serveru. |
Metoda FetchBlobs |
Získává libovolnou položku BLOB pro současný záznam,
když aplikační server nedodává data BLOB automaticky. |
Metoda FetchDetails |
Získává vnořenou datovou množinu pro současný záznam,
když aplikační server je nezahrnuje do datových paketů automaticky. |
Implicitně klientská datová množina získává všechny záznamy
z aplikačního serveru. Pomocí PacketRecords a FetchOnDemand
můžeme řídit jak data jsou získávána. PacketRocords specifikuje
počet najednou získávaných řádků nebo typ vracených záznamů. Implicitně
PacketRecords
je nastaveno na -1, což znamená, že všechny dostupné záznamy jsou získány
najednou a to když aplikace je poprvé otevře nebo aplikace explicitně volá
GetNextPacket.
Když PacketRecords je -1, pak po prvním získání dat, klientská datová
množina nikdy nezíská další data, protože již má všechna dostupná data.
Pro získávání záznamů po malých dávkách, nastavíme PacketRecords
na počet získávaných záznamů. Např. následující příkaz nastavuje velikost
každého datového paketu na 10 záznamů:
ClientDataSet1->PacketRecords = 10;
Tento proces získávání záznamů v dávkách se nazývá inkrementální
získávání. Klientské datové množiny používají inkrementální získávání
když PacketRecords je větší než 0. Implicitně klientská datová množina
volá GetNextPacket k získání dat podle potřeby. Nově získané pakety
jsou připojeny na konec dat již existujících v klientské datové množině.
GetNextPacket vrací počet získaných záznamů. Pokud
vrácená hodnota je stejná jako PacketRecords, pak ještě nebyl dosažen
konec záznamů. Když vrácená hodnota je větší než 0 a menší než PacketRecords,
pak běhen této operace získávání byl získán poslední záznam. Když GetNextPacket
vrací 0, pak již žádný záznam nebyl získán.
PacketRecord můžeme také použít k získání metadatových
informací o databázi z aplikačního serveru. K získání těchto informací
nastavíme
PacketRecords na 0.
Automatické získávání záznamů je řízeno vlastností FetchOnDemand.
Když FetchOnDemand je true (implicitně), pak je povoleno
automatické získávání. K zabránění automatickému získávání záznamů podle
potřeby, nastavíme FetchOnDemand na false. Při tomto nastavení,
aplikace musí explicitně volat GetNextPacket k získání záznamů.
Aplikace, které potřebují extrémně velké datové množiny
určené pouze pro čtení, mohou vypnout FetchOnDamand k zajištění,
že klientská datová množina nezavede více dat než se vejde do paměti. Mezi
získáváním, klientská datová množina vyprázdní svou vyrovnávací paměť pomocí
metody
EmptyDataSet. Toto ale nelze použít, když klient musí odesílat
aktualizace na aplikační server.
Aplikování aktualizací
do databáze
Pokud klientská datová množina je použita jako část klientské
aplikace vice vrstvové databázové aplikace, pak změny zaznamenané klientskou
datovou množinou existují pouze na klientu, dokud nejsou aplikovány na
databázi prostřednictvím aplikačního serveru. K aplikování změn klientské
datové množiny do databáze, voláme metodu ApplyUpdates klientské
datové množiny. ApplyUpdates přebírá změny z deníku změn a zasílá
je jako datové pakety na aplikační server.
ApplyUpdates přebírá jeden parametr, MaxErrors.
MaxErrors
je celé číslo indikující chybovou toleranci chránící před zrušením procesu
aktualizace. Pokud MaxErrors je 0, pak vždy při výskytu chyby aktualizace
na aplikačním serveru je celý aktualizační proces ukončen. Žádné změny
nejsou zapsány do databáze a deník změn klientské datové množiny se nezmění.
Pokud MaxErrors je -1, pak všechny chyby jsou tolerovány a deník
změn obsahuje všechny záznamy, které nemohly být úspěšně aplikovány. Pokud
MaxErrors
je kladná hodnota a vyskytne-li se více chyb než je tato hodnota, pak všechny
změny jsou zrušeny. Pokud se vyskytne méně chyb než je MaxErrors,
pak všechny úspěšně aplikované změny jsou zrušeny v deníku změn klientské
datové množiny.
ApplyUpdates klientské datové množiny volá funkci
Reconcile k zápisu aktualizací do databáze. Reconcile je
funkce zpracovávající chyby, která volá funkci
ApplyUpdates komponenty
poskytovatele na aplikačním serveru. Funkce
ApplyUpdates komponenty
poskytovatele zapíše aktualizace do databáze a pokusí se opravit případné
chyby. Záznamy, které nemohly být aplikovány z důvodu chyb, jsou zaslány
zpět metodě Reconcile klientské datové množiny. Reconcile
se pokusí opravit případné zbývající chyby voláním obsluhy události OnReconcileError.
Tuto obsluhu musíme vytvořit k opravě chyb.
Nakonec Reconcile odstraňuje úspěšně aplikované
změny z deníku změn a aktualizuje Data podle provedených změn. Po
dokončení Reconcile,
ApplyUpdates oznamuje počet zbylých
chyb.
Používání klientských
datových množin bez poskytovatele dat
Klientské datové množiny mohou fungovat nezávisle na poskytovateli,
jako jsou aplikace založené na datech v plochých souborech a aplikace používající
aktovkový model. Zde není poskytovatel a klientská aplikace nemůže získat
definice tabulek a data ze serveru a na server nelze odesílat aktualizace.
Klientská datová množina zde musí:
Vytvořit novou datovou množinu
Jsou tři způsoby definování a vytvoření klientské datové
množiny, která nezískává data od komponenty poskytovatele:
-
Můžeme překopírovat existující datovou množinu (při návrhu
nebo za běhu).
-
Můžeme definovat a vytvořit novou klientskou datovou množinu
vytvářením trvalých položek pro datovou množinu a pak volbou Create
Dataset v místní nabídce ji vytvoříme.
-
Můžeme definovat a vytvořit novou klientskou datovou množinu
na základě definicí položek a definicí indexů.
Zavádění dat ze souboru
nebo proudu
K zavedení dat ze souboru voláme metodu LoadFromFile
klientské datové množiny. LoadFromFile přebírá jeden parametr, řetězec
specifikující soubor se čtenými daty. Jméno souboru může být plně kvalifikované,
pokud to je zapotřebí. Pokud vždy zavádíme data klientské datové množiny
ze stejného souboru, pak můžeme použít vlastnost FileName. Pokud
FileName
obsahuje jméno existujícího souboru, pak data jsou automaticky zavedena,
když klientská datová množina je otevřena.
K zavedení dat z proudu voláme metodu LoadFromStream
klientské datové množiny. LoadFromStream přebírá jeden parametr
a to objekt proudu předávající data.
Data zaváděná LoadFromFile nebo LoadFromStream
musí být dříve uložena v datovém formátu klientské datové množiny touto
nebo jinou klientskou datovou množinou pomocí metody SaveToFile
nebo SaveToStream.
Když voláme LoadFromFile nebo LoadFromStream,
pak všechna data v souboru jsou přečtena do vlastnosti Data. Libovolné
editace, které byly uloženy v deníku změn při uložení dat jsou přečteny
do vlastnosti
Delta.
Slučování změn a dat
Když editujeme data v klientské datové množině, pak provedené
změny
jsou zaznamenány do deníku změn, ale změny neovlivňují původní verzi dat.
K udělání našich změn trvalými, voláme MergeChangeLog. MergeChangeLog
přepíše záznamy v Data změněnými hodnotami položek z deníku změn.
Po provedení MergeChangeLog, vlastnost Data
obsahuje směs existujících dat a změn z deníku změn. Tato směs tvoří základ
pro dále prováděné změny. MergeChangeLog vyprázdní deník změn a
nastaví ChangeCount na 0.
Varování: MergeChangeLog nesmíme volat
pro klientské aplikace, které jsou připojeny na aplikační server. V tomto
případě, voláme
ApplyUpdates k zápisu změn do databáze.
Poznámka: Je také možné slučovat změny s daty
v samostatné klientské datové množině, pokud tato množina původně poskytla
data do vlastnosti
Data. K tomuto musíme použít poskytovatele a
řešitele.
Ukládání dat do souboru
nebo proudu
Pokud používáme klientskou datovou množinu v jedno vrstvové
aplikaci, pak editovaná data a provedené změny existují pouze v paměti.
K trvalému záznamu změn je musíme zapsat na disk. Data na disk můžeme uložit
pomocí metody
SaveToFile.
SaveToFile přebírá jeden parametr, řetězec specifikující
soubor, do kterého budeme zapisovat data. Jméno souboru může být plně kvalifikované,
je-li to zapotřebí. Pokud soubor již existuje, pak jeho obsah je kompletně
přepsán.
Pokud vždy ukládáme data do stejného souboru, pak můžeme
použít vlastnost
FileName. Když FileName je nastaveno, pak
data jsou automaticky uložena do uvedeného souboru při uzavření klientské
datové množiny.
Můžeme také ukládat data do proudu pomocí metody SaveToStream.
SaveToStream
přebírá jeden parametr a to objekt proudu přijímající data.
Poznámka: Pokud ukládáme klientskou datovou
množinu v době kdy není sloučena s deníkem změn, pak data nejsou automaticky
sloučena, ale deník změn je uložen také. Když data opět zavedeme, pak deník
změn obsahuje nesloučené změny. Toto je důležité pro aplikace které podporují
aktovkový model, kde tyto změny mohou být aplikovány na komponentu poskytovatele
na aplikačním serveru.
Poznámka: SaveToFile nechrání žádné
indexy přidané ke klientské datové množině.
|
19. Vytváření a používání klientské
datové množiny
|