Parte 4: Modelli e accesso ai dati

di Jon Galloway

MVC Music Store è un'applicazione di esercitazione che introduce e spiega in modo dettagliato come usare ASP.NET MVC e Visual Studio per lo sviluppo Web.

MVC Music Store è un'implementazione di negozio di esempio leggera che vende album musicali online e implementa l'amministrazione del sito di base, l'accesso utente e la funzionalità del carrello acquisti.

Questa serie di esercitazioni illustra in dettaglio tutti i passaggi eseguiti per compilare l'applicazione di esempio MVC Music Store ASP.NET. La parte 4 illustra i modelli e l'accesso ai dati.

Finora, abbiamo appena passato "dati fittizi" dai controller ai modelli di visualizzazione. A questo momento è possibile collegare un database reale. In questa esercitazione verrà illustrato come usare SQL Server Compact Edition (spesso chiamato SQL CE) come motore di database. SQL CE è un database gratuito, incorporato, basato su file che non richiede alcuna installazione o configurazione, che rende davvero conveniente lo sviluppo locale.

Accesso al database con Entity Framework Code-First

Verrà usato il supporto di Entity Framework (EF) incluso in ASP.NET progetti MVC 3 per eseguire query e aggiornare il database. EF è un'API dati ORM (Flexible Object Relational Mapping) che consente agli sviluppatori di eseguire query e aggiornare i dati archiviati in un database in modo orientato agli oggetti.

Entity Framework versione 4 supporta un paradigma di sviluppo denominato code-first. Code-first consente di creare un oggetto modello scrivendo classi semplici ,note anche come POCO da oggetti CLR "plain-old" e può anche creare il database al volo dalle classi.

Modifiche alle classi di modello

In questa esercitazione verrà usata la funzionalità di creazione del database in Entity Framework. Prima di eseguire questa operazione, tuttavia, verranno apportate alcune modifiche secondarie alle classi di modello da aggiungere in alcuni elementi che verranno usati in un secondo momento.

Aggiunta delle classi del modello di artista

Gli album saranno associati agli artisti, quindi si aggiungerà una classe modello semplice per descrivere un artista. Aggiungere una nuova classe alla cartella Models denominata Artist.cs usando il codice illustrato di seguito.

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

Aggiornamento delle classi di modello

Aggiornare la classe Album, come illustrato di seguito.

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

Eseguire quindi gli aggiornamenti seguenti alla classe 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; }
    }
}

Aggiunta della cartella App_Data

Verrà aggiunta una directory App_Data al progetto per contenere i file di database SQL Server Express. App_Data è una directory speciale in ASP.NET che dispone già delle autorizzazioni di accesso alla sicurezza corrette per l'accesso al database. Dal menu Progetto selezionare Aggiungi ASP.NET Cartella, quindi App_Data.

Screenshot del menu Progetto per aggiungere A S P . N Cartella T per selezionare i dati dell'app.

Creazione di una stringa di connessione nel file web.config

Verranno aggiunte alcune righe al file di configurazione del sito Web in modo che Entity Framework sappia come connettersi al database. Fare doppio clic sul file Web.config che si trova nella radice del progetto.

Screenshot del file di configurazione Web in Esplora soluzioni per creare una stringa di connessione.

Scorrere fino alla fine di questo file e aggiungere una <sezione connectionStrings> direttamente sopra l'ultima riga, come illustrato di seguito.

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

Aggiunta di una classe Context

Fare clic con il pulsante destro del mouse sulla cartella Models e aggiungere una nuova classe denominata MusicStoreEntities.cs.

Screenshot della cartella Models per aggiungere una classe di contesto.

Questa classe rappresenta il contesto del database Entity Framework e gestirà le operazioni create, read, update ed delete. Di seguito è riportato il codice per questa classe.

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

È così: non c'è alcuna altra configurazione, interfacce speciali e così via. Estendendo la classe di base DbContext, la classe MusicStoreEntities è in grado di gestire le operazioni del database. Ora che è stato collegato, aggiungere alcune altre proprietà alle classi di modello per sfruttare alcune delle informazioni aggiuntive nel database.

Aggiunta dei dati del catalogo archivi

Si sfrutta una funzionalità in Entity Framework che aggiunge dati di "seed" a un database appena creato. In questo modo il catalogo dello store verrà precompilato con un elenco di generi, artisti e album. Il download MvcMusicStore-Assets.zip, che include i file di progettazione del sito usati in precedenza in questa esercitazione, include un file di classe con questi dati di inizializzazione, che si trova in una cartella denominata Code.

Nella cartella Code/Models individuare il file SampleData.cs e eliminarlo nella cartella Modelli nel progetto, come illustrato di seguito.

Screenshot della cartella Code o Models per individuare il file Sample Data C S e aggiungere i dati del catalogo archivi.

È ora necessario aggiungere una riga di codice per indicare a Entity Framework la classe SampleData. Fare doppio clic sul file Global.asax nella radice del progetto per aprirlo e aggiungere la riga seguente all'inizio del metodo Application_Start.

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

A questo punto, è stato completato il lavoro necessario per configurare Entity Framework per il progetto.

Esecuzione di query sul database

Ora aggiorniamo StoreController in modo che invece di usare "dati fittizi" viene invece chiamato nel database per eseguire query su tutte le informazioni. Si inizierà dichiarando un campo in StoreController per contenere un'istanza della classe MusicStoreEntities, denominata storeDB:

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

Aggiornamento dell'indice dello Store per eseguire query sul database

La classe MusicStoreEntities viene gestita da Entity Framework ed espone una proprietà di raccolta per ogni tabella nel database. Aggiornare l'azione Indice di StoreController per recuperare tutti i generi nel database. In precedenza è stata eseguita questa operazione tramite i dati di stringa hard-coding. Ora è possibile usare solo l'insieme Generes di contesto Entity Framework:

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

Non è necessario apportare modifiche al modello di visualizzazione perché viene comunque restituito lo stesso StoreIndexViewModel restituito prima di . I dati in tempo reale vengono restituiti dal database.

Quando si esegue di nuovo il progetto e si visita l'URL "/Store", verrà ora visualizzato un elenco di tutti i generi nel database:

Screenshot dell'elenco di tutti i generi nel database.

Aggiornamento di Sfoglia e dettagli dell'archivio per l'uso dei dati in tempo reale

Con il metodo di azione /Store/Browse?genre=[some-genere] viene eseguita la ricerca di un genere in base al nome. Ci aspettiamo solo un risultato, poiché non dovremmo mai avere due voci per lo stesso nome Di genere e quindi possiamo usare . Estensione Single() in LINQ per eseguire query per l'oggetto Genere appropriato, ad esempio questo (non digitare ancora questo):

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

Il metodo Single accetta un'espressione Lambda come parametro, che specifica che si vuole un singolo oggetto Genre in modo che il nome corrisponda al valore definito. Nel caso precedente, viene caricato un singolo oggetto Genre con un valore Name corrispondente a Disco.

Si userà una funzionalità di Entity Framework che consente di indicare altre entità correlate che si desidera caricare anche quando l'oggetto Genre viene recuperato. Questa funzionalità è denominata Query Result Shaping e consente di ridurre il numero di volte in cui è necessario accedere al database per recuperare tutte le informazioni necessarie. Si vuole recuperare gli Album per Genere, quindi si aggiornerà la query da includere da Genres.Include("Albums") per indicare che si vogliono anche album correlati. Questo è più efficiente, poiché recupera i dati di Genere e Album in una singola richiesta di database.

Con le spiegazioni al di fuori del modo, ecco come viene visualizzata l'azione aggiornata del controller Sfoglia:

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

È ora possibile aggiornare la visualizzazione Sfoglia dello Store per visualizzare gli album disponibili in ogni genere. Aprire il modello di visualizzazione (trovato in /Views/Store/Browse.cshtml) e aggiungere un elenco puntato di Album, come illustrato di seguito.

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

L'esecuzione dell'applicazione e l'esplorazione in /Store/Browse?genre=Jazz mostra che i risultati vengono ora estratti dal database, visualizzando tutti gli album nel genere selezionato.

Screenshot dei risultati quando viene eseguito il pull dal database visualizza tutti gli album nel genere selezionato.

Verrà apportata la stessa modifica all'URL /Store/Details/[id] e sostituire i dati fittizi con una query di database che carica un Album il cui ID corrisponde al valore del parametro.

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

L'esecuzione dell'applicazione e l'esplorazione in /Store/Details/1 mostra che i risultati vengono ora estratti dal database.

Screenshot della pagina Dettagli archivio mostra che i risultati vengono estratti anche dal database.

Ora che la pagina Dettagli dello Store è configurata per visualizzare un album dall'ID album, verrà aggiornata la visualizzazione Sfoglia per collegarsi alla visualizzazione Dettagli. Verrà usato Html.ActionLink, esattamente come abbiamo fatto per collegare l'indice dello Store a Sfoglia nello Store alla fine della sezione precedente. L'origine completa per la visualizzazione Sfoglia viene visualizzata di seguito.

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

Ora siamo in grado di esplorare dalla pagina store a una pagina Genere, che elenca gli album disponibili e facendo clic su un album, è possibile visualizzare i dettagli per tale album.

Screenshot della possibilità di passare dalla pagina Store a una pagina Genere.