NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 10 - Scaffolding a Entity Framework v ASP.NET Core MVC

V minulé lekci, Úprava layotu a obsahových stránek v ASP.NET Core MVC , jsme dokončili úpravu struktury výchozí MVC šablony a obsahových stránek tak, aby vypadaly jako osobní blog.

Dnešní ASP.NET Core tutoriál bude nabitý nejmodernějšími technologiemi, pomocí kterých vytvoříme během okamžiku administraci článků na našem blogu. Budeme tak moci na něm psát, ukládat a prezentovat vlastní články.

Budeme pokračovat s projektem z lekce Úprava layotu a obsahových stránek v ASP.NET Core MVC.

Scaffolding

Webové frameworky jsou koncipované tak, aby co nejvíce zjednodušily práci programátora a zejména zredukovaly množství kódu, které musí napsat. Ačkoli se jim to daří, tak stále existují situace, kde je určité množství stereotypního kódu nutné a neexistuje způsob, jakým by ho framework mohl nahradit.

Chystáme se programovat administraci článků na webu a proto budeme potřebovat:

  • kontroler,
  • model článku,
  • databázi pro uložení článků,
  • pohledy pro výpis, editace, přidání, odstranění a detail článků.

Tyto součásti aplikace jednoduše musí obsahovat a nezáleží na tom, v jak geniálním jazyce ji programujeme. Nemusí je však stereotypně psát programátor, ale může je za nás vygenerovat IDE. Tomuto principu se říká scaffolding (nejlepší překlad je asi lešení, kostra). Visual Studio nám jednoduše předgeneruje databázi, kontroler a pohledy. Získáme tak kostru se základní funkčností, kterou pouze upravíme.

Scaffolding v ASP.NET Core MVC - Základy ASP.NET Core MVC

Uložení dat

Námi napsané články budeme muset někam ukládat, budeme tedy potřebovat nějaké úložiště dat. K tomu nám poslouží relační databáze. Tento pojem označuje databázi založenou na tabulkách. Každá tabulka obsahuje položky jednoho typu. Můžeme mít tedy tabulku Uzivatele, další tabulku Clanky a další třeba Komentare.

Databázovou tabulku si můžeme představit třeba jako tabulku v Excelu. Tabulka Uzivatele by mohla vypadat asi takto:

Jméno Příjmení Datum narození Počet článků
Jan Novák 11.3.1984 17
Tomáš Marný 1.2.1989 6
Josef Nový 20.12.1972 9
Michaela Slavíková 14.8.1990 1

Položky (konkrétně zde uživatele) ukládáme na jednotlivé řádky, sloupce pak označují atributy (vlastnosti, chcete-li), které položky mají. Každý sloupec má pevně stanovený datový typ (číslo, znak, krátký text, dlouhý text...) a může obsahovat hodnoty jen tohoto typu.

Pokud chceme s relační databází rozumně pracovat, každý řádek v tabulce by měl být opatřený unikátním identifikátorem. U uživatelů by to mohlo být třeba rodné číslo, mnohem častěji se však používají identifikátory umělé a to tak, že uživatele prostě očíslujeme. V relačních databázích se tento identifikátor též nazývá primární klíč.

MS-SQL databáze

V tomto kurzu využijeme relační databázi typu MS-SQL. Jedná se o velmi sofistikovaný a odladěný nástroj, který za nás řeší spoustu problémů a zároveň je extrémně jednoduchý k použití. S databází komunikujeme jazykem SQL, kterým jsou v podstatě lidsky srozumitelné věty. Nad tímto jazykem vzniklo mnoho nadstaveb a někdy se už dokonce s SQL vůbec nesetkáme. To bude právě i náš případ. S relační databází totiž budeme pracovat pomocí technologie Entity Framework Core.

V naší aplikaci využijeme pouze odlehčenou verzi MS-SQL databáze označovanou jako LocalDB. Tato databáze se nejčastěji používá buďto při vývoji aplikace, a ve finální verzi je nahrazena plnohodnotnou databází, anebo někdy i jako lokální úložiště dat.

Ve druhém případě se však spíše volí databáze SQLite.

Entity Framework Core

Entity Framework Core je tzv. Objektově Relační Mapper (ORM) pro přístup k databázím. Databázové tabulky se přímo mapují na C# třídy, v kódu pracujeme jen s objekty a framework sám na pozadí generuje SQL kód. S jazykem SQL vůbec nepřijdeme do styku a naše aplikace je 100% objektová.

Přístup k databázi je v Entity Framework Core realizován přes tzv. model. Jedná se o popis struktury databáze ve formě C# tříd, který se skládá zejména z entit a databázového kontextu.

Pod entitou si můžeme jednoduše představit tabulku databáze, kterou v C# reprezentujeme třídou. Databázový kontext pak představuje a definuje:

  • samotné propojení s databází,
  • všechny tabulky databáze (entity) a
  • vazby mezi nimi.

Veškerá komunikace s databází probíhá skrze tento databázový kontext.

Code First a Database First přístupy

S Entity Frameworkem lze pracovat dvěma způsoby. Můžeme vytvořit C# třídu (entitu) a Entity Framework Core nám podle ní automaticky vygeneruje databázovou tabulku a potřebný databázový kontext. Tomuto přístupu se říká Code First.

Druhý způsob spočívá v založení databáze, ze které nám Entity Framework vygeneruje entity a databázový kontext. Tento přístup se jmenuje Database First.

Jelikož vytvořit třídu je mnohem jednodušší než vytvořit databázi, zvolíme pro tento tutoriál přístup Code First. I v praxi se jedná o častější volbu.

Podrobně se technologie Entity Framework Core rozebírá buď v samostatném kurzu Entity Framework Core v C# .NET zde na síti, anebo případně v kurzu tvorby webového API ASP.NET Core Web API, ve kterém si přesně ukazujeme, jak Entity Framework Core manuálně napojit na ASP.NET Core aplikaci.

Model databáze

Co se týče modelu databáze, tak zde nám bude stačit vytvořit pouze entitu článku, databázový kontext totiž už máme v projektu vygenerovaný. Jedná se o třídu ApplicationDbContext ve složce Data/. Tato třída nám byla vygenerována již během zakládání projektu, protože jsme zaškrtli možnost Individual Accounts pro podporu autentizace v naší aplikaci. Účty uživatelů naší aplikace se totiž budou ukládat taktéž do databáze. V tomto kontextu jsou zatím zahrnuty pouze tabulky pro uživatelské účty a role.

Entita Article

Protože Entity Framework Core používá určité konvence a převádí názvy tříd do množného čísla, budeme aplikaci psát anglicky, aby názvy nebyly zkomolené. Do složky Models/ si tedy přidejme novou třídu Article. Bude se jednat o naši entitu článku, na základě které se vygeneruje tabulka v databázi. Vlastnosti entity budou představovat jednotlivé sloupce databázové tabulky.

Třída bude vypadat 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 zde několik vlastností, konkrétně:

  • Id – unikátní identifikátor článku,
  • Content – obsah článku,
  • Title – titulek článku,
  • Description – popisek článku.

Id musí mít každá entita. Až z kódu vygenerujeme tabulky, tak se stane jejím primárním klíčem, který bude články jednoznačně odlišovat i kdyby měly třeba stejný titulek.

Od Visual Studio 2022 jsou všechny projekty automaticky generovány s povolenou funkcí nullovatelných referenčních typů (funkce přidána v C# 8.0). Tato funkce nám umožňuje nastavit hodnotu null pouze atributům nebo vlastnostem, které mají definici typu označenou operátorem ?, a to i v případě že se jedná o referenční datový typ. Každý atribut nebo vlastnost referenčního datového typu tak musí mít při vytváření objektu nastavenou nějakou výchozí hodnotu jinou než null, pokud není označen jako nullovatelný operátorem ?. Proto našim vlastnostem nastavujeme jako výchozí hodnotu prázdný řetězec.

Rebuild

Aby uměl Entity Framework Core databázi ze třídy Article vygenerovat, musíme projekt s touto třídou nejprve sestavit (provést rebuild). Toho dosáhneme kliknutím pravým na projekt v Solution Explorer a výběrem možnosti Rebuild. Třída se tím zkompiluje:

Rebuild projektu v ASP.NET Core MVC - Základy ASP.NET Core MVC

Kontroler ArticlesController

Začneme tvorbou zmiňovaného kontroleru pro správu článků. Přidáme si jej do složky Controllers/ kliknutím pravým tlačítkem na danou složku a volbou AddController.... Zobrazí se nám dialog s výběrem scaffoldingu, kde zvolíme MVC Controller with views, using Entity Framework:

Scaffolding controller v ASP.NET Core MVC - Základy ASP.NET Core MVC

Jako model zvolíme naši třídu Article a jako datový kontext vybereme již existující kontext ApplicationDbContext. Název kontroleru ponecháme výchozí ArticlesController a dialog potvrdíme:

Scaffolded controller v ASP.NET Core MVC - Základy ASP.NET Core MVC

Všimněme si, že můžeme nastavit, zda chceme používat layout a několik dalších věcí.

Co se vygenerovalo

Pouze tímto jedním krokem se nám do projektu doinstalovaly všechny potřebné NuGet balíčky s Entity Framework Core a vygenerovaly nebo rozšířily se zbývající třídy modelu databáze.

Dále nám byl vygenerován samotný kontroler ArticlesController s několika akcemi. Nalezneme zde akce:

  • Index() – výpis všech článků,
  • Details() – výpis jednoho článku,
  • Create() – vytvoření článku,
  • Edit() – editace článku,
  • Delete() – odstranění článku.

Když se podíváme do složky Views/, nalezneme zde složku Articles/ a v ní pět pohledů pro tyto akce.

Migrace

Sice již máme vygenerovaný celý databázový model, ale zatím v databázi neexistuje tabulka pro naši entitu Article a dokonce ani samotná databáze. Aby databáze odpovídala našim modelům, musíme na ní provádět tzv. migrace. Jedná se o třídy popisující, jak se má databáze nebo její tabulky vygenerovat.

Ve Visual Studio vybereme v horním menu ToolsNuGet Package ManagerPackage Manager Console. V dolní části okna se nám otevře konzole, do které zadáme příkaz Add-Migration pro vygenerování migrace:

Add-Migration ArticleMigration

ArticleMigration je název naší migrace, můžeme zadat i jakýkoli jiný. Potvrdíme klávesou Enter. Po chvilce se nám ve složce Data/Migrations/ vygeneruje nová třída ArticleMigration představující danou migraci.

Jakmile migraci vytvoříme, musíme ji na databázi aplikovat. To provedeme příkazem Update-Database:

Přidání migrace ArticleMigration ve Visual Studio - Základy ASP.NET Core MVC

Kdykoli rozšíříme databázový model o novou třídu nebo nějakou již existující třídu odstraníme nebo změníme (např. do něj přidáme nějakou vlastnost, nějakou odstraníme apod.), provedeme tento postup. Visual Studio za nás aktualizuje databázi, aby v ní byly všechny změny promítnuté.

Testování

Spustíme aplikaci a přejdeme na odkaz Články:

Seznam článků v ASP.NET Core MVC - Základy ASP.NET Core MVC

Vidíme, že administrace článků se vygenerovala automaticky a je plně funkční. Nejedná se sice zatím o nějaký skvost, v budoucích lekcích to však hravě napravíme. Můžeme si zkusit přidat nějaký testovací článek odkazem Create New:

Přidání nového článku v ASP.NET Core MVC - Základy ASP.NET Core MVC

Zobrazí se nám v seznamu článků:

Seznam článků v ASP.NET Core MVC - Základy ASP.NET Core MVC

A můžeme si ho také otevřít pomocí odkazu Details:

Detail článku v ASP.NET Core MVC - Základy ASP.NET Core MVC

Získání článku z databáze

Všimněme si URL adresy:

http://localhost:44311/Articles/Details/1

První segment cesty označuje název kontroleru ArticlesController, který se má spustit. Druhým segmentem je název jeho akce Details().

O tomto mechanismu, který převádí cestu URL adresy na volání metod kontroleru (routování) jsme si již říkali v předchozích lekcích. Jeho nastavení můžeme měnit v souboru Program.cs.

V předchozích aplikacích jsme měli v kontroleru HomeController vždy jen jednu akci Index() a ta se spustí automaticky, i když žádnou cestu neuvedeme. V souboru Program.cs totiž máme nastavené výchozí směrování na akci Index() kontroleru HomeController:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

Další segmenty v cestě jsou parametry dané akce v kontroleru, zde se jedná o Id článku, který zobrazujeme. Ze vzoru cesty můžeme vyčíst, že takový parametr je nepovinný (znak otazníku ?) a že se akci předává skrze parametr metody s názvem id.

Kontroler ArticlesController

Akce Details() v kontroleru ArticlesController vypadá 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);
}

Opravdu vidíme, že nullovatelný parametr id je zapsán jako obyčejný parametr metody. V případě, že parametr není zadán nebo článek není nalezen, je vrácena odpověď s chybou.

Získání článku z databáze má na svědomí jen tento řádek:

var article = await _context.Article.FirstOrDefaultAsync(m => m.Id == id);

Třídní atribut _context obsahuje instanci databázového kontextu ApplicationDbContext, ve kterém je tabulka s články reprezentována vlastností Article. Z této tabulky se jeden záznam získá jednoduše zavoláním metody FirstOrDefaultAsync(). Pokud jste Entity Framework Core neznali, tak ho nyní asi budete milovat :)

Asynchronní akce

Na této akci zároveň vidíme, že akce kontroleru můžeme klidně zapisovat i jako tzv. asynchronní metody, pokud to potřebujeme. ASP.NET Core si s tím poradí.

Jedná se o metody, které nevrací svou hodnotu ihned, ale až po nějakém časovém intervalu. Mezitím program na návratovou hodnotu volané metody nečeká, ale pokračuje dále ve vykonávání kódu. Takovou metodou je právě metoda FirstOrDefaultAsync(), která vrací svou hodnotu až poté, co ji získá z databáze.

Kód akce následující po volání metody FirstOrDefaultAsync() smí být vykonán až ve chvíli, kdy je k dispozici návratová hodnota této metody. Na návratovou hodnotu je tedy potřeba čekat. Proto se metoda FirstOrDefaultAsync() volá s klíčovým slovem await. Tím se zajistí čekání na návratovou hodnotu a vykonávání akce se pozdrží. Výhodou asynchronních metod je, že procesor může v průběhu čekání vykonávat jakýkoliv jiný kód a efektivněji tak pracovat se svým časem.

Aby se v akci Details() mohla volat asynchronní metoda s klíčovým slovem await, tak musí být sama asynchronní metodou. Toho se dosáhne označením metody klíčovým slovem async.

Více o tomto tématu se dočtete v kurzu Paralelní programování a vícevláknové aplikace v C# .NET.

Databáze je uložená v lokálním souboru, ovšem nikoli ve složce projektu, ale ve vaší uživatelské složce v C:\Users\<vaše jméno>. Můžete se do ní podívat, soubor s databází má příponu .mdf. Toto také znamená, že pokud vám něco nepůjde a budete si chtít dnes nebo kdykoli příště stáhnout hotové řešení pod článkem, databáze v něm nebude a projekt nebude fungovat. Po stažení projektu je nutné vygenerovat databázi příkazem Update-Database v Package Manager Console, čímž se prázdná databáze pro příslušný projekt vytvoří. Poté bude stažený projekt teprve fungovat.

V následujícím cvičení, Řešené úlohy k 8.-10. lekci frameworku ASP.NET Core MVC, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 414x (4.93 MB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Úprava layotu a obsahových stránek v ASP.NET Core MVC
Všechny články v sekci
Základy ASP.NET Core MVC
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 8.-10. lekci frameworku ASP.NET Core MVC
Článek pro vás napsal Martin Petrovaj
Avatar
Uživatelské hodnocení:
302 hlasů
Autor je lenivý vymýšľať nejaký slušný podpis. Venuje sa ale prevažne C#.
Aktivity