Część 4. Modele i dostęp do danych

Autor: Jon Galloway

MvC Music Store to aplikacja samouczka, która wprowadza i wyjaśnia krok po kroku, jak używać ASP.NET MVC i Visual Studio do tworzenia aplikacji internetowych.

MVC Music Store to uproszczona przykładowa implementacja sklepu, która sprzedaje albumy muzyczne online i implementuje podstawową administrację witryny, logowanie użytkowników i funkcjonalność koszyka.

W tej serii samouczków szczegółowo opisano wszystkie kroki podjęte w celu utworzenia przykładowej aplikacji ASP.NET MVC Music Store. Część 4 obejmuje modele i dostęp do danych.

Do tej pory przekazaliśmy "fikcyjne dane" z naszych kontrolerów do szablonów widoków. Teraz jesteśmy gotowi do podłączenia prawdziwej bazy danych. W tym samouczku omówimy sposób używania programu SQL Server Compact Edition (często nazywanego PROGRAMEM SQL CE) jako aparatu bazy danych. SQL CE to bezpłatna, osadzona, oparta na plikach baza danych, która nie wymaga żadnej instalacji ani konfiguracji, co sprawia, że jest to naprawdę wygodne w przypadku lokalnego programowania.

Dostęp do bazy danych za pomocą programu Entity Framework Code-First

Użyjemy obsługi platformy Entity Framework (EF), która jest uwzględniona w projektach ASP.NET MVC 3 w celu wykonywania zapytań i aktualizowania bazy danych. EF to elastyczny interfejs API danych mapowania obiektów (ORM), który umożliwia deweloperom wykonywanie zapytań i aktualizowanie danych przechowywanych w bazie danych w sposób zorientowany obiektowo.

Program Entity Framework w wersji 4 obsługuje paradygmat programowania o nazwie code-first. Kod-first umożliwia tworzenie obiektu modelu przez pisanie prostych klas (nazywanych również POCO z "zwykłych" obiektów CLR), a nawet tworzenie bazy danych na bieżąco z klas.

Zmiany w naszych klasach modeli

W tym samouczku będziemy korzystać z funkcji tworzenia bazy danych w programie Entity Framework. Zanim jednak zrobimy to, wprowadźmy kilka drobnych zmian w naszych klasach modeli, aby dodać niektóre elementy, których będziemy używać później.

Dodawanie klas modelu artysty

Nasze albumy będą skojarzone z artystami, więc dodamy prostą klasę modelu, aby opisać artystę. Dodaj nową klasę do folderu Models o nazwie Artist.cs, korzystając z poniższego kodu.

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

Aktualizowanie klas modeli

Zaktualizuj klasę Album, jak pokazano poniżej.

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; }
    }
}

Następnie wprowadź następujące aktualizacje do klasy Gatunek.

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; }
    }
}

Dodawanie folderu App_Data

Dodamy katalog App_Data do naszego projektu w celu przechowywania plików bazy danych SQL Server Express. App_Data jest specjalnym katalogiem w ASP.NET, który ma już odpowiednie uprawnienia dostępu do zabezpieczeń na potrzeby dostępu do bazy danych. W menu Projekt wybierz pozycję Dodaj folder ASP.NET, a następnie App_Data.

Zrzut ekranu przedstawiający menu Project (Projekt), aby dodać element A S P . N E T Folder, aby wybrać dane aplikacji.

Tworzenie parametrów połączenia w pliku web.config

Dodamy kilka wierszy do pliku konfiguracji witryny internetowej, aby program Entity Framework wiedział, jak nawiązać połączenie z naszą bazą danych. Kliknij dwukrotnie plik Web.config znajdujący się w katalogu głównym projektu.

Zrzut ekranu przedstawiający plik konfiguracji sieci Web w Eksploratorze rozwiązań w celu utworzenia w nim parametrów połączenia.

Przewiń do dołu tego pliku i dodaj sekcję <connectionStrings> bezpośrednio nad ostatnim wierszem, jak pokazano poniżej.

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

Dodawanie klasy kontekstu

Kliknij prawym przyciskiem myszy folder Models i dodaj nową klasę o nazwie MusicStoreEntities.cs.

Zrzut ekranu przedstawiający folder Models, aby dodać klasę kontekstu.

Ta klasa będzie reprezentować kontekst bazy danych platformy Entity Framework i będzie obsługiwać nasze operacje tworzenia, odczytu, aktualizacji i usuwania. Poniżej przedstawiono kod dla tej klasy.

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

To wszystko — nie ma innej konfiguracji, specjalnych interfejsów itp. Rozszerzając klasę bazową DbContext, nasza klasa MusicStoreEntities jest w stanie obsłużyć nasze operacje bazy danych. Teraz, gdy mamy to podłączyć, dodajmy kilka dodatkowych właściwości do naszych klas modeli, aby skorzystać z niektórych dodatkowych informacji w naszej bazie danych.

Dodawanie danych katalogu sklepów

Skorzystamy z funkcji w programie Entity Framework, która dodaje dane "inicjuj" do nowo utworzonej bazy danych. Spowoduje to wstępne wypełnienie katalogu sklepów listą gatunków, artystów i albumów. Pobieranie MvcMusicStore-Assets.zip , które obejmowało pliki projektu witryny używane wcześniej w tym samouczku , zawiera plik klasy z danymi początkowymi znajdującymi się w folderze o nazwie Code.

W folderze Code /Models znajdź plik SampleData.cs i upuść go do folderu Models w naszym projekcie, jak pokazano poniżej.

Zrzut ekranu przedstawiający folder Code or Models w celu zlokalizowania pliku przykładowych danych C S i dodania danych katalogu magazynu.

Teraz musimy dodać jeden wiersz kodu, aby poinformować platformę Entity Framework o tej klasie SampleData. Kliknij dwukrotnie plik Global.asax w katalogu głównym projektu, aby go otworzyć, a następnie dodaj następujący wiersz do góry metody Application_Start.

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

W tym momencie wykonaliśmy pracę niezbędną do skonfigurowania programu Entity Framework dla naszego projektu.

wykonywanie zapytania w bazie danych

Teraz zaktualizujmy naszą funkcję StoreController, aby zamiast używać "fikcyjnych danych", zamiast tego wywołuje ją do naszej bazy danych, aby wykonać zapytanie o wszystkie jego informacje. Zaczniemy od zadeklarowania pola w storeController w celu przechowywania wystąpienia klasy MusicStoreEntities o nazwie storeDB:

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

Aktualizowanie indeksu magazynu w celu wykonywania zapytań względem bazy danych

Klasa MusicStoreEntities jest utrzymywana przez program Entity Framework i uwidacznia właściwość kolekcji dla każdej tabeli w naszej bazie danych. Zaktualizujmy akcję indeksu StoreController, aby pobrać wszystkie gatunki w naszej bazie danych. Wcześniej zrobiliśmy to za pomocą danych ciągów kodowania twardego. Teraz możemy zamiast tego użyć kolekcji Generes kontekstu platformy Entity Framework:

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

Nie trzeba mieć żadnych zmian w szablonie Widok, ponieważ nadal zwracamy ten sam model StoreIndexViewModel, który został zwrócony wcześniej — teraz po prostu zwracamy dane na żywo z naszej bazy danych.

Gdy ponownie uruchomimy projekt i odwiedzimy adres URL "/Store", zobaczymy teraz listę wszystkich gatunków w naszej bazie danych:

Zrzut ekranu przedstawiający listę wszystkich gatunków w bazie danych.

Aktualizowanie przeglądania magazynu i szczegółów w celu korzystania z danych na żywo

Za pomocą metody akcji /Store/Browse?genre=[some-gatunek] wyszukujemy gatunek według nazwy. Oczekujemy tylko jednego wyniku, ponieważ nigdy nie powinniśmy mieć dwóch wpisów dla tej samej nazwy gatunku, a więc możemy użyć elementu . Rozszerzenie Single() w LINQ do wykonywania zapytań dotyczących odpowiedniego obiektu gatunku w następujący sposób (jeszcze tego nie wpisz):

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

Metoda Single przyjmuje wyrażenie Lambda jako parametr, który określa, że chcemy, aby pojedynczy obiekt gatunku był taki, że jego nazwa odpowiada zdefiniowanej wartości. W powyższym przypadku ładujemy pojedynczy obiekt gatunek z wartością Name zgodną z dyskoteką.

Skorzystamy z funkcji platformy Entity Framework, która umożliwia nam wskazanie innych powiązanych jednostek, które chcemy załadować, a także po pobraniu obiektu Gatunek. Ta funkcja jest nazywana kształtowaniem wyników zapytań i umożliwia nam zmniejszenie liczby potrzebnych informacji w celu uzyskania dostępu do bazy danych w celu pobrania wszystkich potrzebnych informacji. Chcemy wstępnie pobrać albumy dla gatunku, więc zaktualizujemy nasze zapytanie, aby uwzględnić je z gatunków.Include("Albumy"), aby wskazać, że chcemy również powiązanych albumów. Jest to bardziej wydajne, ponieważ pobiera zarówno dane gatunku, jak i albumu w pojedynczym żądaniu bazy danych.

W przypadku objaśnień poniżej przedstawiono sposób, w jaki wygląda nasza zaktualizowana akcja Kontrolera przeglądania:

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);
}

Teraz możemy zaktualizować widok przeglądania sklepu, aby wyświetlić albumy, które są dostępne w każdym gatunku. Otwórz szablon widoku (znaleziony w pliku /Views/Store/Browse.cshtml) i dodaj listę punktowaną albumów, jak pokazano poniżej.

@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>

Uruchomienie naszej aplikacji i przejście do /Store/Browse?genre=Jazz pokazuje, że nasze wyniki są teraz ściągane z bazy danych, wyświetlając wszystkie albumy w wybranym gatunku.

Zrzut ekranu przedstawiający wyniki po pobraniu z bazy danych wyświetla wszystkie albumy w wybranym gatunku.

Wprowadzimy tę samą zmianę w adresie URL /Store/Details/[id] i zastąpimy nasze fikcyjne dane zapytaniem bazy danych, które ładuje album, którego identyfikator odpowiada wartości parametru.

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

Uruchomienie naszej aplikacji i przejście do /Store/Details/1 pokazuje, że nasze wyniki są teraz ściągane z bazy danych.

Zrzut ekranu przedstawiający stronę Szczegóły sklepu pokazuje, że wyniki są również pobierane z bazy danych.

Teraz, gdy strona Szczegóły sklepu jest skonfigurowana do wyświetlania albumu według identyfikatora albumu, zaktualizujmy widok Przeglądaj , aby połączyć się z widokiem Szczegóły. Użyjemy narzędzia Html.ActionLink, tak jak w przypadku linku z indeksu sklepu do witryny Store Browse na końcu poprzedniej sekcji. Poniżej zostanie wyświetlone kompletne źródło widoku przeglądania.

@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>

Teraz możemy przejść z naszej strony Sklepu do strony Gatunek, która zawiera listę dostępnych albumów, a następnie klikając album, możemy wyświetlić szczegóły tego albumu.

Zrzut ekranu przedstawiający możliwość przeglądania ze strony Sklep do strony Gatunek.