10. diel - Scaffolding a Entity Framework v ASP.NET Core MVC
V minulej 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ý ASP.NET Core tutoriál 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í, tak 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ácia, pridanie, odstránenie a detail článkov.
Uloženie dát
Nami napísané články budeme musieť niekam ukladať, budeme teda
potrebovať nejaké úložisko dát. K tomu 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
Uzivatele
, ďalšiu tabuľku Clanky
a ďalšie
napríklad Komentare
.
Databázovú tabuľku si môžeme predstaviť napríklad ako tabuľku v Exceli. Tabuľka Uzivatele
by
mohla vyzerať asi takto:
Meno | Priezvisko | Dátum narodenia | Počet článkov |
---|---|---|---|
Ján | Novák | 11.3.1984 | 17 |
Tomáš | Márny | 1.2.1989 | 6 |
Jozef | Nový | 20.12.1972 | 9 |
Michaela | Sláviková | 14.8.1990 | 1 |
Pokiaľ chceme s relačnou databázou rozumne pracovať, každý riadok v tabuľke by mal byť opatrený unikátnym identifikátorom. U uží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 užívateľov jednoducho očíslujeme. V relačných databázach sa tento identifikátor tiež nazýva primárny kľúč.
MS-SQL databázy
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. O bjektovo R elačné M apper (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.
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 v založení 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 tento tutoriál 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 tu na sieti, alebo prípadne v kurze tvorby webového 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 uží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.
Views/
, nájdeme tu zložku
Articles/
av 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
pre
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 Články:
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:44311/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 akciu 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 .SingleOrDefaultAsync(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.SingleOrDefaultAsync(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
SingleOrDefaultAsync()
. Pokiaľ 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, pokiaľ 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 SingleOrDefaultAsync()
, ktorá vracia svoju hodnotu
až potom, čo ju získa z databázy.
Kód akcie nasledujúci po volaní metódy
SingleOrDefaultAsync()
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 SingleOrDefaultAsync()
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 jméno>
. Môžete sa do nej pozrieť, súbor
s databázou má príponu .mdf
. Toto tiež znamená, že
pokiaľ 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. lekciu 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é 414x (4.93 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#