NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 1 - Úvod do Entity Framework Core v C# .NET

Vítejte u první lekce kurzu o programování databázových aplikací s použitím technologie Entity Framework Core. Po absolvování tohoto kurzu budeme umět pracovat s relačními databázemi zcela objektovým přístupem, pouze v jazyce C# .NET. Při komunikaci s jakoukoliv databází tak již nebudeme muset napsat ani jeden řádek SQL kódu.

V dnešním Entity Framework Core tutoriálu si uvedeme různé způsoby práce s relačními databázemi v C# .NET a porovnáme je s fungováním Entity Framework Core.

Požadavky na znalosti

Tento kurz předpokládá kromě znalostí v rozsahu:

taktéž:

  • minimálně teoretické znalosti z kurzu Databáze v C# - ADO.NET a
  • základní znalosti relačních databázových technologií spolu s jazykem SQL.

Přestože v tomto kurzu nebudeme psát žádný SQL kód, tak je dobré mu alespoň rozumět. A to především při snaze o různé optimalizace nebo při hledání chyb ve vygenerovaném SQL kódu. Námi napsaný C# kód se totiž musí nakonec vždy přeložit na SQL příkazy, které jsou volány na samotné databázi.

V kurzu budeme pracovat především s MS-SQL databází, s níž se můžete blíže seznámit v samostatném kurzu jen o MS-SQL databázi MS-SQL databáze krok za krokem.

Přístupy k relační databázi v .NET

Relační databáze jsou časem ověřený způsob jak pracovat s daty. Díky tomu tento typ databází dominuje celému trhu a jejich použití se tak při tvorbě aplikací mnohdy nevyhneme. Relační databáze však na rozdíl od jazyka C# nefungují objektově a komunikace s nimi tedy není úplně přímočará.

Z kurzu Databáze v C# - ADO.NET již víme, že v .NET existuje několik možností, jak se s tímto vypořádat. V rychlosti si je připomeneme.

Existují i databáze plně objektové. Příkladem takové databáze je třeba MongoDB. Více v lekci Úvod do MongoDB.

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ž C# je objektový jazyk, ani by to v něm dost dobře nešlo.

V .NET se tomuto přístupu nejvíce blíží použití třídy SqlCommand, pomocí které lze přímo na databázi zasílat SQL dotazy. Data z databáze jsou nám vrácena v podobě pole hodnot. Ukažme si použití této třídy na jednoduchém příkladu databáze s tabulkou uživatelů Users:

FirstName LastName BirthDate
Jan Novák 11.3.1984
Michaela Slavíková 14.8.1990
Josef Nový 20.12.1972

Kód pro vypsání všech uživatelů seřazených podle data narození vypadá následovně:

using (SqlConnection connection = new SqlConnection(ConnectionString))
{
    connection.Open();

    string query = "SELECT FirstName, LastName FROM Users ORDER BY BirthDate;";
    SqlCommand command = new SqlCommand(query, connection);

    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine($"Jméno: {reader.GetString(0)}, Příjmení: {reader.GetString(1)}");
        }
    }
}

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.

V .NET je tento přístup realizován třídami SqlDataAdapter a DataSet. DataSet v sobě obsahuje 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 DataAdapter, pomocí kterého si naplníme DataSet daty. Příkazy již musíme psát v jazyce SQL dané databáze.

Stejný výpis tabulky z příkladu výše bychom s použitím tříd SqlDataAdapter a DataSet provedli takto:

using (SqlConnection connection = new SqlConnection(ConnectionString))
{
    connection.Open();

    string query = "SELECT FirstName, LastName FROM Users ORDER BY BirthDate;";

    using (SqlDataAdapter adapter = new SqlDataAdapter(query, connection))
    using (DataSet result = new DataSet())
    {
        adapter.Fill(result);

        foreach (DataRow row in result.Tables[0].Rows)
        {
            Console.WriteLine($"Jméno: {row["FirstName"]}, Příjmení: {row["LastName"]}");
        }
    }
}

Máme tedy určitou objektovou abstrakci, s tabulkami pracujeme objektově, ale data jsou stále jen sloupečky v tabulce. Také stále používáme jazyk SQL.

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 a ty na sobě mají 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 samozřejmě 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í).

.NET naštěstí perfektně odladěné ORM nabízí, je jím právě Entity Framework Core.

Názory na ORM jsou velmi kontroverzní. Například ž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í od práce s relační databází tedy není úplné.

Entity Framework Core

Entity Framework Core (EF Core) je tedy tzv. Objektově Relační Mapper (ORM) pro přístup k databázím. Vychází ze staršího Entity Frameworku, na rozdíl od kterého je ale rozšiřitelný, zcela open source a především multiplatformní.

Tuto technologii vyvíjí přímo Microsoft, má tak vcelku jistou dlouhodobou podporu.

Jak EF Core zhruba funguje

Abychom měli porovnání všech možností práce s databází kompletní, tak si nakonec ještě nastíníme, jak v Entity Framework Core funguje samotný přístup k databázi. Podrobně si vše však rozebereme až v budoucích lekcích. Následující kód tedy berme čistě jen jako ukázku, nemusíme v něm zatím úplně všemu rozumět.

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

Entita

Pod entitou si můžeme jednoduše představit tabulku databáze, kterou v C# reprezentujeme třídou. Například entita přestavující uživatele z příkladu výše by mohla vypadat následovně:

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}

Jednotlivé záznamy tabulky Users pak chápeme jako instance této třídy User.

Záznamy tabulky budeme někdy zjednodušeně označovat taktéž pojmem "entita".

Databázový kontext

Databázový kontext pak představuje a definuje samotné propojení s databází, všechny tabulky databáze (entity) a vazby mezi nimi. Databázový kontext s tabulkou Users z příkladu výše by mohl vypadat třeba takto:

public class AppDbContext : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(ConnectionString);
    }
}

Čtení dat

Jakékoliv dotazy na databázi následně voláme prostřednictvím instance našeho databázového kontextu:

using (AppDbContext dbContext = new AppDbContext())
{
    IList<User> users = dbContext.Users.OrderBy(user => user.LastName).ToList();

    foreach (User user in users)
    {
        Console.WriteLine($"Jméno: {user.FirstName}, Příjmení: {user.LastName}");
    }
}

Vidíme, že pro získání všech uživatelů z databáze jsme nemuseli do C# kódu vmíchat žádný SQL příkaz a udrželi tak jeho jednoduchost a především čitelnost. S tabulkami databáze pracujeme podobným způsobem jako s kolekcemi. Dobrá čitelnost je zajištěna i díky LINQ metodám, které Entity Framework Core podporuje pro vybírání dat z databáze.

LINQ metody jsme probírali v lekci LINQ v C# .NET - Revoluce v dotazování.

Poskytovatelé databází

Výše zmiňovaná rozšiřitelnost souvisí s tím, že přes Entity Framework Core můžeme přistupovat k mnoha různým databázím prostřednictvím dodatečných knihoven označovaných jako poskytovatelé databází (database providers). Přímo Microsoft například vyvíjí poskytovatele pro MS-SQL a SQLite databáze. Poskytovatelé pro PostgreSQL, Oracle nebo MySQL databáze jsou však již vyvíjeni třetími stranami.

Poskytovatele databází si, stejně jako samotný Entity Framework Core, instalujeme skrze NuGet balíčky. Pro výše uvedené databáze to jsou například balíčky:

Seznam těch nejvýznamnějších poskytovatelů nalezneme v oficiální dokumentaci.

To by bylo pro úvodní lekci vše.

V příští lekci, Instalace a první model v Entity Framework Core a C# .NET, si založíme náš první projekt s Entity Framework Core a vytvoříme jednoduchý model.


 

Všechny články v sekci
Entity Framework Core v C# .NET
Přeskočit článek
(nedoporučujeme)
Instalace a první model v Entity Framework Core a C# .NET
Článek pro vás napsal Radek Vymětalík
Avatar
Uživatelské hodnocení:
47 hlasů
...
Aktivity