Část 4: Modely a přístup k datům

Jon Galloway

MVC Music Store je kurzová aplikace, která představuje a vysvětluje, jak používat ASP.NET MVC a Visual Studio pro vývoj pro web.

MVC Music Store je jednoduchá ukázková implementace obchodu, která prodává hudební alba online a implementuje základní správu webu, přihlašování uživatelů a funkce nákupního košíku.

Tato série kurzů podrobně popisuje všechny kroky potřebné k vytvoření ukázkové aplikace ASP.NET MVC Music Store. Část 4 se věnuje modelům a přístupu k datům.

Zatím jsme jenom předávali "fiktivní data" z našich kontrolerů do šablon zobrazení. Teď jsme připraveni připojit skutečnou databázi. V tomto kurzu se budeme zabývat tím, jak používat SQL Server Compact Edition (často označovanou jako SQL CE) jako náš databázový stroj. SQL CE je bezplatná vložená souborová databáze, která nevyžaduje žádnou instalaci ani konfiguraci, takže je opravdu vhodná pro místní vývoj.

Přístup k databázi pomocí entity frameworku Code-First

K dotazování a aktualizaci databáze použijeme podporu Entity Frameworku (EF), která je součástí projektů ASP.NET MVC 3. EF je flexibilní rozhraní API pro relační mapování objektů (ORM), které vývojářům umožňuje dotazovat a aktualizovat data uložená v databázi objektově orientovaným způsobem.

Entity Framework verze 4 podporuje vývojové paradigma označované jako code-first. Code-first umožňuje vytvořit objekt modelu psaním jednoduchých tříd (označovaných také jako POCO z "prostých" objektů CLR) a dokonce můžete vytvořit databázi za chodu z vašich tříd.

Změny v našich třídách modelů

V tomto kurzu budeme využívat funkci vytváření databáze v Entity Frameworku. Než to ale uděláme, udělejme v našich modelových třídách několik drobných změn, abychom přidali některé věci, které budeme používat později.

Přidání tříd modelů interpretů

Naše alba budou přidružená k umělcům, takže přidáme jednoduchou třídu modelu, která popíše interpreta. Přidejte novou třídu do složky Models s názvem Artist.cs pomocí kódu uvedeného níže.

namespace MvcMusicStore.Models
{
    public class Artist
    {
        public int ArtistId { get; set; }
        public string Name { get; set; }
    }
}

Aktualizace našich tříd modelů

Aktualizujte třídu Album, jak je znázorněno níže.

namespace MvcMusicStore.Models
{
    public class Album
    {
        public int      AlbumId     { get; set; }
        public int      GenreId     { get; set; }
        public int      ArtistId    { get; set; }
        public string   Title       { get; set; }
        public decimal  Price       { get; set; }
        public string   AlbumArtUrl { get; set; }
        public Genre    Genre       { get; set; }
        public Artist   Artist      { get; set; }
    }
}

Dále proveďte následující aktualizace třídy Genre.

using System.Collections.Generic;
 
namespace MvcMusicStore.Models
{
    public partial class Genre
    {
        public int      GenreId     { get; set; }
        public string   Name        { get; set; }
        public string   Description { get; set; }
        public List<Album> Albums   { get; set; }
    }
}

Přidání složky App_Data

Do projektu přidáme adresář App_Data, který bude obsahovat soubory SQL Server Express databáze. App_Data je speciální adresář v ASP.NET, který už má správná přístupová oprávnění zabezpečení pro přístup k databázi. V nabídce Projekt vyberte Přidat složku ASP.NET a pak App_Data.

Snímek obrazovky s nabídkou Projekt pro přidání A S P N E T Složka pro výběr dat aplikace.

Vytvoření připojovacího řetězce v souboru web.config

Do konfiguračního souboru webu přidáme několik řádků, aby Entity Framework věděl, jak se připojit k naší databázi. Poklikejte na Web.config soubor umístěný v kořenovém adresáři projektu.

Snímek obrazovky s konfiguračním souborem webu v Průzkumníku řešení pro vytvoření připojovacího řetězce

Posuňte se do dolní části tohoto souboru a přidejte <část connectionStrings> přímo nad poslední řádek, jak je znázorněno níže.

<connectionStrings>
    <add name="MusicStoreEntities"
     connectionString="Data Source=|DataDirectory|MvcMusicStore.sdf"
     providerName="System.Data.SqlServerCe.4.0"/>
  </connectionStrings>  
</configuration>

Přidání třídy context

Klikněte pravým tlačítkem na složku Models a přidejte novou třídu s názvem MusicStoreEntities.cs.

Snímek obrazovky se složkou Models pro přidání třídy Context

Tato třída bude představovat kontext databáze Entity Framework a zpracuje naše operace vytvoření, čtení, aktualizace a odstranění za nás. Níže vidíte kód pro tuto třídu.

using System.Data.Entity;
 
namespace MvcMusicStore.Models
{
    public class MusicStoreEntities : DbContext
    {
        public DbSet<Album> Albums { get; set; }
        public DbSet<Genre> Genres { get; set; }
    }
}

To je vše – neexistuje žádná jiná konfigurace, speciální rozhraní atd. Rozšířením základní třídy DbContext je naše třída MusicStoreEntities schopna zpracovávat naše databázové operace za nás. Teď, když jsme to propojí, přidáme do tříd modelu několik dalších vlastností, abychom mohli využít některé další informace v naší databázi.

Přidání dat katalogu úložiště

Využijeme funkci v Entity Frameworku, která přidá "počáteční" data do nově vytvořené databáze. Tím se náš katalog obchodů předem naplní seznamem žánrů, interpretů a alb. Soubor MvcMusicStore-Assets.zip ke stažení, který zahrnoval soubory návrhu webu použité dříve v tomto kurzu, obsahuje soubor třídy s tímto počátečním datem umístěný ve složce s názvem Code.

Ve složce Code / Models vyhledejte soubor SampleData.cs a přetáhněte ho do složky Models v našem projektu, jak je znázorněno níže.

Snímek obrazovky se složkou Kód nebo Modely pro vyhledání souboru Sample Data C S a přidání dat katalogu úložiště

Teď musíme přidat jeden řádek kódu, který entity Framework řekne o této třídě SampleData. Poklikáním na soubor Global.asax v kořenovém adresáři projektu ho otevřete a přidejte následující řádek na začátek metody Application_Start.

protected void Application_Start()
{
    System.Data.Entity.Database.SetInitializer(
    new MvcMusicStore.Models.SampleData());
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
 }

V tomto okamžiku jsme dokončili práci potřebnou ke konfiguraci Entity Frameworku pro náš projekt.

Dotazy do databáze

Teď aktualizujeme StoreController tak, aby místo použití "fiktivních dat" volal do naší databáze dotazování všech svých informací. Začneme deklarováním pole na StoreControlleru , které bude obsahovat instanci třídy MusicStoreEntities s názvem storeDB:

public class StoreController : Controller
{
    MusicStoreEntities storeDB = new MusicStoreEntities();

Aktualizace indexu úložiště pro dotazování databáze

Třída MusicStoreEntities je spravována rozhraním Entity Framework a zveřejňuje vlastnost kolekce pro každou tabulku v naší databázi. Pojďme aktualizovat akci Index storeControlleru tak, aby načetla všechny žánry v naší databázi. Dříve jsme to udělali tak, že pevně zakódovali řetězcová data. Teď můžeme místo toho použít jenom kolekci kontextovýchgenerů Entity Frameworku:

public ActionResult Index()
{
    var genres = storeDB.Genres.ToList();
    return View(genres);
 }

V šabloně Zobrazení nemusí docházet k žádným změnám, protože stále vracíme stejný model StoreIndexViewModel, který jsme vrátili dříve – teď jenom vracíme živá data z naší databáze.

Když projekt znovu spustíme a navštívíme adresu URL "/Store", zobrazí se v naší databázi seznam všech žánrů:

Snímek obrazovky se seznamem všech žánrů v databázi

Aktualizace procházení a podrobností služby Store tak, aby používala živá data

Pomocí metody akce /Store/Browse?žánr=[some-žánr] hledáme Žánr podle názvu. Očekáváme pouze jeden výsledek, protože bychom nikdy neměli mít dvě položky pro stejný název Žánr, a proto můžeme použít . Rozšíření Single() v LINQ pro dotazování na příslušný objekt Žánr, jako je tento (zatím nezadávejte):

var example = storeDB.Genres.Single(g => g.Name == "Disco");

Metoda Single přebírá výraz Lambda jako parametr, který určuje, že chceme jeden objekt Genre tak, aby jeho název odpovídal hodnotě, kterou jsme definovali. Ve výše uvedeném případě načítáme jeden objekt Žánr s hodnotou Name odpovídající disco.

Využijeme funkci Entity Framework, která nám umožní označit i další související entity, které chceme načíst při načtení objektu Genre. Tato funkce se nazývá Tvarování výsledků dotazu a umožňuje nám snížit počet potřebných přístupů k databázi, abychom získali všechny potřebné informace. Chceme předem načíst alba pro žánr, který načítáme, a proto aktualizujeme náš dotaz tak, aby zahrnoval z Pole Žánry.Include("Alba"), aby bylo možné naznačit, že chceme také související alba. To je efektivnější, protože načte data o žánru i albu v jediném požadavku databáze.

S vysvětlením, která jsou mimo cestu, vypadá naše aktualizovaná akce kontroleru Procházet takto:

public ActionResult Browse(string genre)
{
    // Retrieve Genre and its Associated Albums from database
    var genreModel = storeDB.Genres.Include("Albums")
        .Single(g => g.Name == genre);

    return View(genreModel);
}

Teď můžeme aktualizovat zobrazení store procházet, aby se zobrazila alba, která jsou k dispozici v jednotlivých žánrech. Otevřete šablonu zobrazení (najdete ji v souboru /Views/Store/Browse.cshtml) a přidejte seznam alb s odrážkami, jak je znázorněno níže.

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>
<ul>
    @foreach (var album in Model.Albums)
    {
        <li>
            @album.Title
        </li>
    }
</ul>

Spuštěním naší aplikace a přechodem na /Store/Browse?žánr=Jazz se teď načítají výsledky z databáze a zobrazí se všechna alba ve vybraném žánru.

Snímek obrazovky s výsledky při výběru z databáze zobrazuje všechna alba ve vybraném žánru.

Provedeme stejnou změnu adresy URL /Store/Details/[id] a nahradíme naše fiktivní data databázovým dotazem, který načte album, jehož ID odpovídá hodnotě parametru.

public ActionResult Details(int id)
{
    var album = storeDB.Albums.Find(id);
 
    return View(album);
}

Spuštěním naší aplikace a přechodem na /Store/Details/1 ukazuje, že se naše výsledky nyní natahují z databáze.

Snímek obrazovky se stránkou Store Details (Podrobnosti obchodu) ukazuje, že se výsledky také natahují z databáze.

Teď, když je stránka Podrobností obchodu nastavená tak, aby zobrazovala album podle ID alba, aktualizujeme zobrazení Procházet tak, aby odkazoval na zobrazení Podrobnosti. Použijeme Html.ActionLink, stejně jako jsme na konci předchozí části vytvořili propojení z indexu Storu na Procházení obchodu. Úplný zdroj zobrazení Procházet se zobrazí níže.

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>
<ul>
    @foreach (var album in Model.Albums)
    {
        <li>
            @Html.ActionLink(album.Title,
"Details", new { id = album.AlbumId })
        </li>
    }
</ul>

Teď můžeme přejít ze stránky Storu na stránku Žánr, na které jsou uvedena dostupná alba, a kliknutím na album můžeme zobrazit podrobnosti o daném albu.

Snímek obrazovky s možností procházení ze stránky Store na stránku Žánr