26.11.2019, Vladimír Klaus, navštíveno 1987x

Delphi

Pokud pro tabulku potřebujete využít tzv. Lookup pole - tedy na základě klíče používat hodnotu z jiné tabulky, není to nic složitého. Klasickým příkladem mohou být třeba objednávky, které odkazují na ID zákazníka a vy potřebujete v tabulce s objednávkami vidět jeho jméno a další detaily.

Dá se to sice dělat až na úrovni zobrazovacích komponent (v případě Developer Express komponent třeba TcxEditRepositoryLookupComboBoxItem), ale proč nevyužít vestavěný systém?

Do tabulky tedy přidáte nové pole typu Lookup, a nastavíte příslušná pole a klíče - to ale není předmětem tohoto článku.

Delphi, ADO a Lookup pole - problémy a řešení pomocí LookupCache, obr. 1

Potud je všechno v pořádku a zřejmě s tím nebudete mít sebemenší problém. Ale to jen do chvíle, kdy se odkazujete (tímto polem) na druhou tabulku, přičemž váš klíč je null (tedy např. u objednávky chybí odkaz na zákazníka). To se pak samozřejmě cílová hodnota nenajde a nemělo by to způsobovat žádný problém. To je ale pravda jen v runtimu. V debug modu to bohužel krachuje a to několikrát za sebou (zřejmě v závislosti na počtu využití takového pole). Chyba je také více než úsměvná a nijak vám v pátrání nepomůže. A určitě bych nedoporučoval využít zaškrtávátko "Ignore this exception type"!

Delphi, ADO a Lookup pole - problémy a řešení pomocí LookupCache, obr. 2

Po řadě pokusů opravit něco, co by opravu nemělo potřebovat, narazíte možná na podobné stížnosti a také na možné řešení. Tím řešením je pro všechna daná lookup pole nastavení vlastnosti LookupCache:=true. V mém případě to opravdu zabralo, ale ještě, než budete jásat, měli byste si přečíst všechny možné dopady tohoto nastavení.

Co je téměř k neuvěření, že řešení jsem našel v příspěvku, který je v době psaní tohoto článku 15 let starý. Tedy za celou dobu se nikdo z autorů DB systému (Microsoft, Embarcadero…?) nenamáhal danou situaci korektně ošetřit. Je to tím více zarážející, že výše uvedené řešení má jisté vedlejší efekty, může vyžadovat další kroky a rozhodně není ideální.

Nakonec jsem zvolil kompromis, tedy v design modu mám nastaveno kešování, abych mohl aplikaci debugovat bez této otravné výjimky, ale v runtimu toto vypínám. Uvidíme, jaká bude praxe a případně sem dopíšu nějaké další zkušenosti.

Musím přidat ještě malou ne úplně související poznámku - pro tyto Lookup hrátky nemůžete využít pole typu Blob (a zřejmě i nějaké další). Zapomeňte tedy na to, že byste takto jednoduše zobrazovali z vedlejší tabulky třeba obrázky. V takovém případě už musíte použít místo Table nějakou Query komponentu a tabulky spojit přes JOIN.

Zdroje: