Lekce 4 - Přístupy pro práci s relačními databázemi ve VB.NET
V minulé lekci, Vytvoření tabulky v databázi ve Visual Studio ve VB.NET, jsme si připravili databázi slovíček.
V dnešním Databáze - ADO.NET tutoriálu si popíšeme problémy relačního a objektového světa a dále přístupy, jakými můžeme s databází v VB.NET pracovat.
Rozpor objektového a relačního přístupu
Objektový svět a svět relačních databází je rozdílný. Jsou to 2 odlišné filozofie, které jsou neslučitelné. Relační databáze jsou ověřený způsob jak pracovat s daty. Ačkoli existují plně objektové databáze, zatím se neprosadily. Relační databáze objektově nefungují a neumí ukládat objekty. Existuje několik možností, jak se s tímto vypořádat.
Neobjektové programování
První možností je samozřejmě programovat úplně bez objektů. Tím bychom však šli proti proudu. Nemohli bychom používat žádné komponenty třetích stran a náš kód by byl velmi nekvalitní. Jelikož VB.NET je objektový jazyk, ani by to v něm dost dobře nešlo.
Databázový Wrapper
Přístup tzv. wrapperu nám umožňuje s databází pracovat jako s objektem, nicméně komunikujeme s ní stále v jejím jazyce SQL. Mícháme tedy objektový a relační kód. Přístup je jakýmsi kompromisem a vyžaduje filozofii OOP trochu ohnout. Výhodou je zachování výkonu a schopností databáze za cenu mírné degradace myšlenek OOP.
Data z databáze vidíme nejčastěji jako hodnoty v tabulce (ta je objektem) a přicházíme o možnost přidělit entitám nějakou funkcionalitu. Tu místo toho sdružujeme do tzv. manažerů. Lze i částečně mapovat data na existující třídy, nicméně plnohodnotného konceptu objektového modelu nedosáhneme.
Objektově relační mapování
Objektově relační mapování (ORM) jde ortodoxně za myšlenkou OOP. Z databáze tedy místo pole hodnot dostáváme rovnou objekty, které mají na sobě metody. V jazyce SQL vůbec nekomunikujeme. Tabulky v databázi vidíme jako kolekce objektů, se kterými můžeme pracovat běžnými prostředky jazyka. Jsme vlastně úplně odstíněni od toho, že pracujeme s relační databází. Zní to skvěle, že?
Háček je v tom, že na pozadí dochází k velké degradaci výkonu databáze, SQL dotazy se generují automaticky a jsou často neefektivní. Dalším problémem ORM je, že je velmi složité (ne k použití, ale k naprogramování). VB.NET má naštěstí perfektně odladěné ORM přímo v sobě, čili nemusíme nic řešit.
Např. zprovoznit ORM v PHP není nic jednoduchého, a proto se tam preferuje přístup wrapperu.
Názory na ORM jsou velmi kontroverzní např. že samotná jeho myšlenka je nesprávná, jelikož generovaný SQL kód zkrátka nemůže být efektivní a je nutné pomýšlet na jeho konečnou podobu. Odstínění tedy není úplné.
Objektové databáze
Kromě databází relačních existují i již zmíněné databáze objektové. Ty řeší problém neslučitelnosti objektového a relačního přístupu. Poskytují stejný komfort jako ORM, ale vnitřně není třeba data převádět do tabulek. Ukládají se rovnou jako objekty.
Teoreticky neexistuje výkonnostní ani jiný důvod, proč by neměly nahradit databáze relační. V praxi se ale bohužel téměř nepoužívají a můžeme jen doufat, že se to časem změní. Zájemci se mohou podívat např. na projekt MongoDB.
Možnosti připojení k databázi
V .NET máme několik možností, jak databázi v naší aplikaci používat. Ke každé možnosti si něco krátce řekněme.
Připojená aplikace
Přístup připojené aplikace použijeme ve chvíli, kdy potřebujeme data
často v reálném čase číst nebo měnit.
Pomocí tříd DataReader
, Command
a
Connection
posíláme databázi přímo příkazy v jazyce SQL a
dostáváme výsledky.
Situace je znázorněna na obrázku:
Odpojená aplikace -
DataSet
Přístup odpojené aplikace funguje tak, že máme v operační paměti
kolekci objektů typu DataSet
, který v sobě obsahuje data z
databáze. Aplikace pracuje s kolekcí typu DataSet
a občas se
tato kolekce sesynchronizuje s ostrou databází na serveru (disku). Za cenu
méně aktuálních dat získáváme zvýšení rychlosti a pohodlnější
práci. Tento přístup shrnuje komponenta ADO.NET, která je
součástí .NET frameworku.
Instance typu DataSet
obsahuje v sobě tabulky, tabulka řádky
a řádek sloupce. Tabulka je objekt. Můžeme do ní řádky
přidávat a upravovat je bez psaní SQL kódu. Když chceme spustit na
databázi nějaký příkaz, použijeme objekt typu DataAdapter
,
pomocí kterého si naplníme instanci DataSet
daty. Příkazy již
musíme psát v jazyce SQL dané databáze.
Situace vypadá následovně:
Máme tedy určitou objektovou abstrakci. S tabulkami pracujeme objektově, ale data jsou stále jen sloupečky v tabulce, ne instance nějakých objektů. Také stále používáme jazyk SQL. Z hlediska výše uvedených přístupů se jedná o wrapper.
LINQ To SQL
LINQ to SQL
poskytuje kompletní objektovou abstrakci nad databází
(objektově relační mapování). S databází pracujeme jako kdyby to byla
např. kolekce objektů typu List
. Vůbec neřešíme SQL dotazy,
nevíme o tabulkách ani sloupcích, vše se děje na pozadí automaticky. Dotaz
nám vrací rovnou plnohodnotné objekty. Cena za takový luxus
je horší optimalizace dotazů, která ale většinou nevadí.
V naší aplikaci figuruje objekt typu DataClasses
, což je
objektová struktura databáze. Obsahuje třídy pro
jednotlivé tabulky. Sloupce tabulky jsou vlastnosti daných tříd. V aplikaci
komunikujeme pouze s tímto objektem. Ten komunikuje s databází na pozadí
pomocí LINQ to SQL a provádí za nás SQL dotazy. My s jazykem SQL vůbec
nepřijdeme do styku a s databází pracujeme jako s objektovou strukturou v
operační paměti.
Situaci bychom znázornili takto:
Entity Framework
Entity framework jde ještě dále, než LINQ to SQL. Jedná se o konkurenční a pokročilejší technologii k LINQ to SQL. Navíc umí např. vazbu M:N. Tento přístup se nejlépe používá, a pokud nejsme nějak limitovaní architekturou dané aplikace nebo výkonem, je dobrou volbou pro většinu aplikací.
V našem kurzu si představíme postupně všechny přístupy.
V příští lekci, Připojená databázová aplikace ve VB.NET, se připojíme k databázi pomocí třídy
SqlConnection
a vytvoříme objekt typu SqlCommand
, na
kterém zavoláme metodu ExecuteScalar()
, abychom zjistili počet
řádků v databázi.