19. Vytváření a používání klientské datové množiny

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í:

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:
  1. Ze stránky MIDAS Palety komponent, přidáme komponentu TClientDataSet k naši aplikaci.
  2. 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.
  3. 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.
  4. 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.
  5. 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:
  1. 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.
  2. Ze stránky MIDAS Palety komponent přidáme k aplikaci komponentu TClientDataSet.
  3. 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.
  4. 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.
  5. 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:
  1. Vytvořit více vrstvovou serverovou aplikaci.
  2. 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.
  3. 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.
  4. 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: Je několik možností, jak to provést, ale následující sekvence kroků zajistí minimum potřebné práce:
  1. Vytvoříme nový projekt pro aplikační server, počínaje vzdáleným modulem dat.
  2. 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.
  3. Z kopie naší dvouvrstvové aplikace odstraníme její přímé databázové připojení a přidáme k ní potřebnou komponentu propojení.
  4. Nahradíme v původním projektu každou datovou množinu BDE klientskou datovou množinou.
  5. Do klientské aplikace přidáme kód aplikující odložené aktualizace na aplikační server.
  6. 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ů: 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: 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: 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ě: 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:

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