10. diel - Scaffolding a Entity Framework v ASP.NET Core MVC
V predchádzajúcej lekcii, Úprava layotu a obsahových stránok v ASP.NET Core MVC , sme dokončili úpravu štruktúry východiskovej MVC šablóny a obsahových stránok tak, aby vyzerali ako osobný blog.
Dnešná lekcia ASP.NET Core bude nabitá najmodernejšími technológiami, pomocou ktorých vytvoríme behom okamihu administráciu článkov na našom blogu. Budeme tak môcť na ňom písať, ukladať a prezentovať vlastné články.
Budeme pokračovať s projektom z lekcie Úprava layotu a obsahových stránok v ASP.NET Core MVC.
Scaffolding
Webové frameworky sú koncipované tak, aby čo najviac zjednodušili prácu programátora a najmä zredukovali množstvo kódu, ktoré musí napísať. Hoci sa im to darí, stále existujú situácie, kde je určité množstvo stereotypného kódu potrebné a neexistuje spôsob, akým by ho framework mohol nahradiť.
Chystáme sa programovať administráciu článkov na webe a preto budeme potrebovať:
- kontrolér,
- model článku,
- databázu na uloženie článkov,
- pohľady pre výpis, editáciu, pridanie, odstránenie a detail článkov.
Tieto súčasti aplikácie jednoducho musia obsahovať a nezáleží na tom, v akom geniálnom jazyku ju programujeme. Nemusí ich však stereotypne písať programátor, ale môže ich za nás vygenerovať IDE. Tomuto princípu sa hovorí scaffolding (najlepší preklad je asi lešenie, kostra). Visual Studio nám jednoducho predgeneruje databázu, kontrolér a pohľady. Získame tak kostru so základnou funkčnosťou, ktorú iba upravíme.

Uloženie dát
Nami napísané články budeme musieť niekam ukladať, budeme teda
potrebovať nejaké úložisko dát. Na to nám poslúži relačná
databáza. Tento pojem označuje databázu založenú na tabuľkách.
Každá tabuľka obsahuje položky jedného typu. Môžeme mať teda tabuľku
Users, ďalšiu tabuľku Articles a ďalšie
napríklad Comments.
Databázovú tabuľku si môžeme predstaviť napríklad ako tabuľku v Exceli. Tabuľka Users by mohla
vyzerať asi takto:
| First Name | Last Name | Date of Birth | Number of Articles |
|---|---|---|---|
| John | Smith | 1984-03-11 | 17 |
| Thomas | Brown | 1989-02-01 | 6 |
| Joseph | Johnson | 1972-12-20 | 9 |
| Michelle | Davis | 1990-08-14 | 1 |
Položky (tu konkrétne používatelia) ukladáme na jednotlivé riadky, stĺpce potom označujú atribúty (vlastnosti, ak chcete), ktoré položky majú. Každý stĺpec má pevne stanovený dátový typ (číslo, znak, krátky text, dlhý text...) a môže obsahovať hodnoty iba tohto typu.
Ak chceme s relačnou databázou rozumne pracovať, každý riadok v tabuľke by mal byť opatrený unikátnym identifikátorom. U používateľov by to mohlo byť potrebné rodné číslo, oveľa častejšie sa však používajú identifikátory umelé a to tak, že používateľov jednoducho očíslujeme. V relačných databázach sa tento identifikátor tiež nazýva primárny kľúč.
MS-SQL databáza
V tomto kurze využijeme relačnú databázu typu MS-SQL. Jedná sa o veľmi sofistikovaný a odladený nástroj, ktorý za nás rieši množstvo problémov a zároveň je extrémne jednoduchý na použitie. S databázou komunikujeme jazykom SQL, ktorým sú v podstate ľudsky zrozumiteľné vety. Nad týmto jazykom vzniklo mnoho nadstavieb a niekedy sa už dokonca s SQL vôbec nestretneme. To bude práve aj náš prípad. S relačnou databázou totiž budeme pracovať pomocou technológie Entity Framework Core.
V našej aplikácii využijeme iba odľahčenú verziu MS-SQL databázy označovanú ako LocalDB. Táto databáza sa najčastejšie používa buď pri vývoji aplikácie, a vo finálnej verzii je nahradená plnohodnotnou databázou, alebo niekedy aj ako lokálne úložisko dát.
V druhom prípade sa však skôr volí databáza SQLite.
Entity Framework Core
Entity Framework Core je tzv. Objektovo Relačný Mapper (ORM) pre prístup k databázam. Databázové tabuľky sa priamo mapujú na C# triedy, v kóde pracujeme len s objektmi a framework sám na pozadí generuje SQL kód. S jazykom SQL vôbec neprídeme do styku a naša aplikácia je 100% objektová.
Prístup k databáze je v Entity Framework Core realizovaný cez tzv. model. Ide o popis štruktúry databázy vo forme C# tried, ktorý sa skladá najmä z entít a databázového kontextu.
Pod entitou si môžeme jednoducho predstaviť tabuľku databázy, ktorú v C# reprezentujeme triedou. Databázový kontext potom predstavuje a definuje:
- samotné prepojenie s databázou,
- všetky tabuľky databázy (entity) a
- väzby medzi nimi.
Všetka komunikácia s databázou prebieha cez tento databázový kontext.
Code First a Database First prístupy
S Entity Frameworkom je možné pracovať dvoma spôsobmi. Môžeme vytvoriť C# triedu (entitu) a Entity Framework Core nám podľa nej automaticky vygeneruje databázovú tabuľku a potrebný databázový kontext. Tomuto prístupu sa hovorí Code First.
Druhý spôsob spočíva vo vytvorení databázy, z ktorej nám Entity Framework vygeneruje entity a databázový kontext. Tento prístup sa volá Database First.
Keďže vytvoriť triedu je oveľa jednoduchšie ako vytvoriť databázu, zvolíme pre túto lekciu prístup Code First. Aj v praxi sa jedná o častejšiu voľbu.
Podrobne sa technológia Entity Framework Core rozoberá buď v samostatnom kurze Entity Framework Core v C# .NET tu na sieti, alebo prípadne v kurze tvorby webového API ASP.NET Core Web API, v ktorom si presne ukazujeme, ako Entity Framework Core manuálne napojiť na ASP.NET Core aplikáciu.
Model databázy
Čo sa týka modelu databázy, tak tu nám bude stačiť vytvoriť iba entitu
článku, databázový kontext totiž už máme v projekte vygenerovaný. Ide o
triedu ApplicationDbContext v priečinku Data/. Táto
trieda nám bola vygenerovaná už počas zakladania projektu, pretože sme
zaškrtli možnosť Individual Accounts na podporu autentizácie v
našej aplikácii. Účty používateľov našej aplikácie sa totiž budú
ukladať taktiež do databázy. V tomto kontexte sú zatiaľ zahrnuté iba
tabuľky pre používateľské účty a roly.
Entita Article
Pretože Entity Framework Core používa určité konvencie a prevádza
názvy tried do množného čísla, budeme aplikáciu písať anglicky, aby
názvy neboli skomolené. Do zložky Models/ si teda pridajme novú
triedu Article. Bude sa jednať o našu entitu článku, na
základe ktorej sa vygeneruje tabuľka v databáze. Vlastnosti entity budú
predstavovať jednotlivé stĺpce databázovej tabuľky.
Trieda bude vyzerať takto:
public class Article { public int Id { get; set; } public string Content { get; set; } = ""; public string Title { get; set; } = ""; public string Description { get; set; } = ""; }
Máme tu niekoľko vlastností, konkrétne:
Id– unikátny identifikátor článku,Content– obsah článku,Title– titulok článku,Description– popis článku.
Id musí mať každá entita. Až z kódu vygenerujeme tabuľky,
tak sa stane jej primárnym kľúčom, ktorý bude články jednoznačne
odlišovať aj keby mali napríklad rovnaký titulok.
Od Visual Studio 2022 sú všetky projekty automaticky
generované s povolenou funkciou nullovateľných referenčných
typov (funkcia pridaná v C# 8.0). Táto funkcia nám umožňuje
nastaviť hodnotu null iba atribútom alebo vlastnostiam, ktoré
majú definíciu typu označenú operátorom ?, a to aj v prípade
že sa jedná o referenčný dátový typ. Každý atribút
alebo vlastnosť referenčného dátového typu tak musí mať pri vytváraní
objektu nastavenú nejakú východiskovú hodnotu inú ako null,
pokiaľ nie je označený ako nullovateľný operátorom ?. Preto
našim vlastnostiam nastavujeme ako predvolenú hodnotu prázdny reťazec.
Rebuild
Aby vedel Entity Framework Core databázu z triedy Article
vygenerovať, musíme projekt s touto triedou najprv zostaviť (vykonať
rebuild). To dosiahneme kliknutím pravým na projekt v Solution
Explorer a výberom možnosti Rebuild. Trieda sa tým
skompiluje:

Kontrolér
ArticlesController
Začneme tvorbou spomínaného kontroléra pre správu článkov. Pridáme si
ho do zložky Controllers/ kliknutím pravým tlačidlom na danú
zložku a voľbou Add → Controller.... Zobrazí sa nám
dialóg s výberom scaffoldingu, kde zvolíme MVC Controller with views,
using Entity Framework:

Ako model zvolíme našu triedu Article a ako dátový kontext
vyberieme už existujúci kontext ApplicationDbContext. Názov
kontroléra ponecháme predvolený ArticlesController a dialóg
potvrdíme:

Všimnime si, že môžeme nastaviť, či chceme používať layout a niekoľko ďalších vecí.
Čo sa vygenerovalo
Iba týmto jedným krokom sa nám do projektu doinštalovali všetky potrebné NuGet balíčky s Entity Framework Core a vygenerovali alebo rozšírili sa zostávajúce triedy modelu databázy.
Ďalej nám bol vygenerovaný samotný kontrolér
ArticlesController s niekoľkými akciami. Nájdeme tu akcie:
Index()– výpis všetkých článkov,Details()– výpis jedného článku,Create()– vytvorenie článku,Edit()– editácia článku,Delete()– odstránenie článku.
Keď sa pozrieme do zložky Views/, nájdeme tu zložku
Articles/ a v nej päť pohľadov pre tieto akcie.
Migrácia
Síce už máme vygenerovaný celý databázový model, ale zatiaľ v
databáze neexistuje tabuľka pre našu entitu
Article a dokonca ani samotná databáza. Aby databáza zodpovedala
našim modelom, musíme na nej vykonávať tzv. migrácie. Ide
o triedy popisujúce, ako sa má databáza alebo jej tabuľky vygenerovať.
Vo Visual Studio vyberieme v hornom menu Tools → NuGet Package
Manager → Package Manager Console. V dolnej časti okna sa nám
otvorí konzola, do ktorej zadáme príkaz Add-Migration na
vygenerovanie migrácie:
Add-Migration ArticleMigration
ArticleMigration je názov našej migrácie, môžeme zadať aj
akýkoľvek iný. Potvrdíme klávesom Enter. Po chvíľke sa nám v
zložke Data/Migrations/ vygeneruje nová trieda
ArticleMigration predstavujúca danú migráciu.
Akonáhle migráciu vytvoríme, musíme ju na databázu aplikovať. To
vykonáme príkazom Update-Database:

Kedykoľvek rozšírime databázový model o novú triedu alebo nejakú už existujúcu triedu odstránime alebo zmeníme (napr. do neho pridáme nejakú vlastnosť, nejakú odstránime a pod.), vykonáme tento postup. Visual Studio za nás aktualizuje databázu, aby v nej boli všetky zmeny premietnuté.
Testovanie
Spustíme aplikáciu a prejdeme na odkaz Articles:

Vidíme, že administrácia článkov sa vygenerovala automaticky a je plne funkčná. Nejedná sa síce zatiaľ o nejaký skvost, v budúcich lekciách to však hravo napravíme. Môžeme si skúsiť pridať nejaký testovací článok odkazom Create New:

Zobrazí sa nám v zozname článkov:

A môžeme si ho tiež otvoriť pomocou odkazu Details:

Získanie článku z databázy
Všimnime si URL adresy:
http://localhost:7038/Articles/Details/1
Prvý segment cesty označuje názov kontroléra
ArticlesController, ktorý sa má spustiť. Druhým segmentom je
názov jeho akcie Details().
O tomto mechanizme, ktorý prevádza cestu URL adresy na volanie
metód kontroléra (rútovania) sme si už hovorili v predchádzajúcich
lekciách. Jeho nastavenia môžeme meniť v súbore
Program.cs.
V predchádzajúcich aplikáciách sme mali v kontroléri
HomeController vždy len jednu akciu Index() a tá sa
spustí automaticky, aj keď žiadnu cestu neuvedieme. V súbore
Program.cs totiž máme nastavené východiskové smerovanie na
akciu Index() kontroléra HomeController:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Ďalšie segmenty v ceste sú parametre danej akcie v
kontroléri, tu sa jedná o Id článku, ktorý zobrazujeme. Zo
vzoru cesty môžeme vyčítať, že takýto parameter je nepovinný (znak
otáznika ?) a že sa akcii odovzdáva skrz parameter metódy s
názvom id.
Kontrolér
ArticlesController
Akcia Details() v kontroléri ArticlesController
vyzerá takto:
// GET: Articles/Details/5 public async Task<IActionResult> Details(int? id) { if (id == null) { return NotFound(); } var article = await _context.Article .FirstOrDefaultAsync(m => m.Id == id); if (article == null) { return NotFound(); } return View(article); }
Naozaj vidíme, že nullovateľný parameter id je zapísaný
ako obyčajný parameter metódy. V prípade, že parameter nie je zadaný alebo
článok nie je nájdený, je vrátená odpoveď s chybou.
Získanie článku z databázy má na svedomí len tento riadok:
var article = await _context.Article.FirstOrDefaultAsync(m => m.Id == id);
Triedny atribút _context obsahuje inštanciu databázového
kontextu ApplicationDbContext, v ktorom je tabuľka s článkami
reprezentovaná vlastnosťou Article. Z tejto tabuľky sa jeden
záznam získa jednoducho zavolaním metódy FirstOrDefaultAsync().
Ak ste Entity Framework Core nepoznali, tak ho teraz asi budete milovať 
Asynchrónne akcie
Na tejto akcii zároveň vidíme, že akcie kontroléra môžeme pokojne zapisovať aj ako tzv. asynchrónne metódy, ak to potrebujeme. ASP.NET Core si s tým poradí.
Ide o metódy, ktoré nevracajú svoju hodnotu ihneď, ale až po nejakom
časovom intervale. Medzitým program na návratovú hodnotu volanej metódy
nečaká, ale pokračuje ďalej vo vykonávaní kódu. Takouto metódou je
práve metóda FirstOrDefaultAsync(), ktorá vracia svoju hodnotu
až potom, čo ju získa z databázy.
Kód akcie nasledujúci po volaní metódy FirstOrDefaultAsync()
smie byť vykonaný až vo chvíli, keď je k dispozícii návratová hodnota
tejto metódy. Na návratovú hodnotu je teda potrebné čakať. Preto sa
metóda FirstOrDefaultAsync() volá s kľúčovým slovom
await. Tým sa zaistí čakanie na návratovú hodnotu a
vykonávanie akcie sa pozdrží. Výhodou asynchrónnych metód je, že procesor
môže v priebehu čakania vykonávať akýkoľvek iný kód a efektívnejšie
tak pracovať so svojím časom.
Aby sa v akcii Details() mohla volať asynchrónna metóda s
kľúčovým slovom await, tak musí byť sama asynchrónnou
metódou. To sa dosiahne označením metódy kľúčovým slovom
async.
Viac o tejto téme sa dočítate v kurze Paralelné programovanie a viacvláknové aplikácie v C# .NET.
Databáza je uložená v lokálnom súbore, ale nie v
priečinku projektu, ale vo vašej používateľskej zložke v
C:\Users\<vaše meno>. Môžete sa do nej pozrieť, súbor s
databázou má príponu .mdf. To tiež znamená, že ak
vám niečo nepôjde a budete si chcieť dnes alebo kedykoľvek nabudúce
stiahnuť hotové riešenie pod článkom, databáza v ňom nebude a projekt
nebude fungovať. Po stiahnutí projektu je nutné vygenerovať
databázu príkazom Update-Database v Package Manager
Console, čím sa prázdna databáza pre príslušný projekt vytvorí.
Potom bude stiahnutý projekt ešte len fungovať.
V nasledujúcom cvičení, Riešené úlohy k 8.-10. lekcii frameworku ASP.NET Core MVC, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 6x (4.33 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#
