Esercitazione: Introduzione a EF Core in un'app Web ASP.NET MVCTutorial: Get started with EF Core in an ASP.NET MVC web app

Questa esercitazione non è stata aggiornata ad ASP.NET Core 3.0.This tutorial has not been updated to ASP.NET Core 3.0. La versione di Razor Pages è stata aggiornata.The Razor Pages version has been updated. Per informazioni su quando questo potrebbe essere aggiornato, vedere questo problema in GitHub.For information on when this might be updated, see this GitHub issue.

Questa esercitazione illustra ASP.NET Core MVC ed Entity Framework Core con i controller e le viste.This tutorial teaches ASP.NET Core MVC and Entity Framework Core with controllers and views. Razor Pages è un modello di programmazione alternativo introdotto in ASP.NET Core 2.0.Razor Pages is an alternative programming model that was introduced in ASP.NET Core 2.0. Per le nuove attività di sviluppo, è consigliabile usare Razor Pages rispetto a MVC con controller e visualizzazioni.For new development, we recommend Razor Pages over MVC with controllers and views. È disponibile una versione di questa esercitazione per Razor Pages.There is a Razor Pages version of this tutorial. Ogni esercitazione illustra alcuni materiali che l'altra versione non contiene:Each tutorial covers some material the other doesn't:

Alcuni elementi presenti in questa esercitazione su MVC, ma che non sono contenuti nell'esercitazione su Razor Pages:Some things this MVC tutorial has that the Razor Pages tutorial doesn't:

  • Implementare l'ereditarietà nel modello di datiImplement inheritance in the data model
  • Eseguire query SQL non elaboratePerform raw SQL queries
  • Usare LINQ dinamico per semplificare il codiceUse dynamic LINQ to simplify code

Alcuni elementi presenti nell'esercitazione su Razor Pages, ma che non sono contenuti in questa esercitazione:Some things the Razor Pages tutorial has that this one doesn't:

  • Usare il metodo Select per caricare i dati correlatiUse Select method to load related data
  • Versione disponibile per ASP.NET Core 3.0A version available for ASP.NET Core 3.0

L'applicazione Web di esempio di Contoso University illustra come creare applicazioni Web ASP.NET Core 2.2 MVC con Entity Framework (EF) Core 2.2 e Visual Studio 2017 o 2019.The Contoso University sample web application demonstrates how to create ASP.NET Core 2.2 MVC web applications using Entity Framework (EF) Core 2.2 and Visual Studio 2017 or 2019.

L'applicazione di esempio è un sito Web per una fittizia Contoso University.The sample application is a web site for a fictional Contoso University. Include funzionalità, come ad esempio l'ammissione di studenti, la creazione di corsi e le assegnazioni di insegnati.It includes functionality such as student admission, course creation, and instructor assignments. Questa è la prima di una serie di esercitazioni che illustrano come compilare da zero l'app di esempio di Contoso University.This is the first in a series of tutorials that explain how to build the Contoso University sample application from scratch.

Le attività di questa esercitazione sono le seguenti:In this tutorial, you:

  • Creare un'app Web ASP.NET Core MVCCreate an ASP.NET Core MVC web app
  • Impostare lo stile del sitoSet up the site style
  • Scoprire di più sui pacchetti NuGet di EF CoreLearn about EF Core NuGet packages
  • Creare il modello di datiCreate the data model
  • Creare il contesto di databaseCreate the database context
  • Registrare il contesto per l'inserimento delle dipendenzeRegister the context for dependency injection
  • Inizializzare il database con i dati di testInitialize the database with test data
  • Creare controller e visualizzazioniCreate a controller and views
  • Visualizzare il databaseView the database

PrerequisitiPrerequisites

Risoluzione dei problemiTroubleshooting

Se si verifica un problema che non si sa come risolvere, è generalmente possibile trovare la soluzione confrontando il codice con il progetto completato.If you run into a problem you can't resolve, you can generally find the solution by comparing your code to the completed project. Per un elenco degli errori comuni e delle relative soluzioni, vedere la sezione relativa alla risoluzione dei problemi nell'ultima esercitazione della serie.For a list of common errors and how to solve them, see the Troubleshooting section of the last tutorial in the series. Se non si trova la soluzione, è possibile inviare una domanda a StackOverflow.com per ASP.NET Core o Entity Framework Core.If you don't find what you need there, you can post a question to StackOverflow.com for ASP.NET Core or EF Core.

Suggerimento

In questa serie di 10 esercitazioni ogni esercitazione si basa su quanto viene eseguito nelle esercitazioni precedenti.This is a series of 10 tutorials, each of which builds on what is done in earlier tutorials. È consigliabile salvare una copia del progetto dopo aver completato ogni esercitazione.Consider saving a copy of the project after each successful tutorial completion. Se si verificano problemi, è possibile ricominciare dall'esercitazione precedente anziché tornare all'inizio della serie.Then if you run into problems, you can start over from the previous tutorial instead of going back to the beginning of the whole series.

App Web di Contoso UniversityContoso University web app

L'applicazione che sarà compilata in queste esercitazioni è un semplice sito Web universitario.The application you'll be building in these tutorials is a simple university web site.

Gli utenti possono visualizzare e aggiornare le informazioni che riguardano studenti, corsi e insegnanti.Users can view and update student, course, and instructor information. Di seguito sono disponibili alcune schermate che saranno create.Here are a few of the screens you'll create.

Pagina Student Index (Indice degli studenti)

Pagina Students Edit (Modifica studenti)

Creare un'app WebCreate web app

  • Aprire Visual Studio.Open Visual Studio.

  • Scegliere Nuovo > Progetto dal menu File.From the File menu, select New > Project.

  • Nel riquadro sinistro selezionare Installato > Visual C# > Web.From the left pane, select Installed > Visual C# > Web.

  • Selezionare il modello di progetto Applicazione Web ASP.NET Core.Select the ASP.NET Core Web Application project template.

  • Immettere ContosoUniversity come nome e fare clic su OK.Enter ContosoUniversity as the name and click OK.

    Finestra di dialogo Nuovo progetto

  • Attendere che venga visualizzata la finestra di dialogo Nuova applicazione Web ASP.NET Core.Wait for the New ASP.NET Core Web Application dialog to appear.

  • Selezionare .NET Core, ASP.NET Core 2.2 e il modello Applicazione Web (MVC) .Select .NET Core, ASP.NET Core 2.2 and the Web Application (Model-View-Controller) template.

  • Assicurarsi che per Autenticazione sia impostata l'opzione Nessuna autenticazione.Make sure Authentication is set to No Authentication.

  • Scegliere OK.Select OK

    Finestra di dialogo Nuovo progetto ASP.NET Core

Impostare lo stile del sitoSet up the site style

Con alcune modifiche è possibile impostare il menu del sito, il layout e la home page.A few simple changes will set up the site menu, layout, and home page.

Aprire Views/Shared/_Layout.cshtml e apportare le modifiche seguenti:Open Views/Shared/_Layout.cshtml and make the following changes:

  • Modificare tutte le occorrenze di "ContosoUniversity" in "Contoso University".Change each occurrence of "ContosoUniversity" to "Contoso University". Le occorrenze sono tre.There are three occurrences.

  • Aggiungere le voci di menu per About (Informazioni su), Students (Studenti), Courses (Corsi), Instructors (Insegnanti) e Departments (Dipartimenti) ed eliminare la voce di menu Privacy.Add menu entries for About, Students, Courses, Instructors, and Departments, and delete the Privacy menu entry.

Le modifiche vengono evidenziate.The changes are highlighted.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Contoso University</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
              crossorigin="anonymous"
              integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
    </environment>
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Contoso University</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="About">About</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Students" asp-action="Index">Students</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Courses" asp-action="Index">Courses</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Instructors" asp-action="Index">Instructors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Departments" asp-action="Index">Departments</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <partial name="_CookieConsentPartial" />
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - Contoso University - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
        </script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
        </script>
    </environment>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

In Views/Home/Index.cshtml sostituire il contenuto del file con il codice seguente. In questo modo il testo su ASP.NET e MVC sarà sostituito dal testo relativo a questa applicazione:In Views/Home/Index.cshtml, replace the contents of the file with the following code to replace the text about ASP.NET and MVC with text about this application:

@{
    ViewData["Title"] = "Home Page";
}

<div class="jumbotron">
    <h1>Contoso University</h1>
</div>
<div class="row">
    <div class="col-md-4">
        <h2>Welcome to Contoso University</h2>
        <p>
            Contoso University is a sample application that
            demonstrates how to use Entity Framework Core in an
            ASP.NET Core MVC web application.
        </p>
    </div>
    <div class="col-md-4">
        <h2>Build it from scratch</h2>
        <p>You can build the application by following the steps in a series of tutorials.</p>
        <p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">See the tutorial &raquo;</a></p>
    </div>
    <div class="col-md-4">
        <h2>Download it</h2>
        <p>You can download the completed project from GitHub.</p>
        <p><a class="btn btn-default" href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-mvc/intro/samples/cu-final">See project source code &raquo;</a></p>
    </div>
</div>

Premere CTRL+F5 per eseguire il progetto oppure selezionare Debug > Avvia senza eseguire debug dal menu.Press CTRL+F5 to run the project or choose Debug > Start Without Debugging from the menu. La home page sarà visualizzata con le schede create in queste esercitazioni.You see the home page with tabs for the pages you'll create in these tutorials.

Home page di Contoso University

Informazioni sui pacchetti NuGet di EF CoreAbout EF Core NuGet packages

Per aggiungere il supporto di Entity Framework Core a un progetto, installare il provider di database di destinazione.To add EF Core support to a project, install the database provider that you want to target. Questa esercitazione usa SQL Server e il pacchetto del provider è Microsoft.EntityFrameworkCore.SqlServer.This tutorial uses SQL Server, and the provider package is Microsoft.EntityFrameworkCore.SqlServer. Poiché il pacchetto è incluso nel metapacchetto Microsoft.AspNetCore.App, non è necessario inserire alcun riferimento al pacchetto.This package is included in the Microsoft.AspNetCore.App metapackage, so you don't need to reference the package.

Il pacchetto EF SQL Server e le relative dipendenze (Microsoft.EntityFrameworkCore e Microsoft.EntityFrameworkCore.Relational) offrono supporto di runtime per Entity Framework.The EF SQL Server package and its dependencies (Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.Relational) provide runtime support for EF. Nell'esercitazione Migrazioni viene aggiunto un pacchetto di strumenti.You'll add a tooling package later, in the Migrations tutorial.

Per informazioni su altri provider di database disponibili per Entity Framework Core, vedere Provider di database.For information about other database providers that are available for Entity Framework Core, see Database providers.

Creare il modello di datiCreate the data model

A questo punto è possibile creare le classi delle entità per l'applicazione di Contoso University.Next you'll create entity classes for the Contoso University application. Si inizia con le tre entità seguenti.You'll start with the following three entities.

Diagramma modello di dati Course/Enrollment/Student (Corso/Iscrizione/Studente)

Esiste una relazione uno-a-molti tra le entità Student e Enrollment ed esiste una relazione uno-a-molti tra le entità Course e Enrollment.There's a one-to-many relationship between Student and Enrollment entities, and there's a one-to-many relationship between Course and Enrollment entities. In altre parole, uno studente può iscriversi a un numero qualsiasi di corsi e un corso può avere un numero qualsiasi di studenti iscritti.In other words, a student can be enrolled in any number of courses, and a course can have any number of students enrolled in it.

Nelle sezioni seguenti viene creata una classe per ognuna di queste entità.In the following sections you'll create a class for each one of these entities.

Entità Student (Studente)The Student entity

Diagramma entità Student (Studente)

Nella cartella Models (Modelli) creare un file di classe denominato Student.cs e sostituire il codice del modello con il codice seguente.In the Models folder, create a class file named Student.cs and replace the template code with the following code.

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

La proprietà ID diventa la colonna di chiave primaria della tabella di database che corrisponde a questa classe.The ID property will become the primary key column of the database table that corresponds to this class. Per impostazione predefinita, Entity Framework interpreta una proprietà denominata ID o classnameID come chiave primaria.By default, the Entity Framework interprets a property that's named ID or classnameID as the primary key.

La proprietà Enrollments rappresenta una proprietà di navigazione.The Enrollments property is a navigation property. Le proprietà di navigazione contengono altre entità correlate a questa entità.Navigation properties hold other entities that are related to this entity. In questo caso la proprietà Enrollments di Student entity contiene tutte le entità Enrollment correlate all'entità Student.In this case, the Enrollments property of a Student entity will hold all of the Enrollment entities that are related to that Student entity. In altre parole, se una determinata riga Student (Studente) nel database contiene due righe Enrollment (Iscrizione) correlate (le righe che contengono il valore della chiave primaria dello studente nella colonna della chiave esterna StudentID), la proprietà di navigazione Enrollments dell'entità Student contiene quelle due entità Enrollment.In other words, if a given Student row in the database has two related Enrollment rows (rows that contain that student's primary key value in their StudentID foreign key column), that Student entity's Enrollments navigation property will contain those two Enrollment entities.

Se una proprietà di navigazione può contenere più entità (come nel caso di relazioni molti-a-molti e uno-a-molti), il tipo della proprietà deve essere un elenco in cui le voci possono essere aggiunte, eliminate e aggiornate, come ad esempio ICollection<T>.If a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be a list in which entries can be added, deleted, and updated, such as ICollection<T>. È possibile specificare ICollection<T> o un tipo come List<T> o HashSet<T>.You can specify ICollection<T> or a type such as List<T> or HashSet<T>. Se si specifica ICollection<T>, per impostazione predefinita Entity Framework crea una raccolta HashSet<T>.If you specify ICollection<T>, EF creates a HashSet<T> collection by default.

Entità Enrollment (Iscrizione)The Enrollment entity

Diagramma entità Enrollment (Iscrizione)

Nella cartella Models creare Enrollment.cs e sostituire il codice esistente con il codice seguente:In the Models folder, create Enrollment.cs and replace the existing code with the following code:

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }

        public Course Course { get; set; }
        public Student Student { get; set; }
    }
}

La proprietà EnrollmentID sarà la chiave primaria. Questa entità usa il criterio classnameID anziché ID come descritto per l'entità Student.The EnrollmentID property will be the primary key; this entity uses the classnameID pattern instead of ID by itself as you saw in the Student entity. In genere si sceglie un criterio e lo si usa poi in tutto il modello di dati.Ordinarily you would choose one pattern and use it throughout your data model. In questo caso la variazione illustra che è possibile sia uno sia l'altro criterio.Here, the variation illustrates that you can use either pattern. In un'esercitazione successiva viene illustrato l'uso di ID senza classname. In questo modo si semplifica l'implementazione dell'ereditarietà nel modello di dati.In a later tutorial, you'll see how using ID without classname makes it easier to implement inheritance in the data model.

La proprietà Grade è un oggettoenum.The Grade property is an enum. Il punto interrogativo dopo la dichiarazione del tipo Grade indica che la proprietà Grade ammette i valori Null.The question mark after the Grade type declaration indicates that the Grade property is nullable. Un voto il cui valore è Null è diverso da un voto con valore zero. Null significa che un voto è sconosciuto o non è stato ancora assegnato.A grade that's null is different from a zero grade -- null means a grade isn't known or hasn't been assigned yet.

La proprietà StudentID è una chiave esterna e la proprietà di navigazione corrispondente è Student.The StudentID property is a foreign key, and the corresponding navigation property is Student. Un'entità Enrollment è associata a un'entità Student, pertanto la proprietà può contenere un'unica entità Student, a differenza della proprietà di navigazione Student.Enrollments vista in precedenza, che può contenere più entità Enrollment.An Enrollment entity is associated with one Student entity, so the property can only hold a single Student entity (unlike the Student.Enrollments navigation property you saw earlier, which can hold multiple Enrollment entities).

La proprietà CourseID è una chiave esterna e la proprietà di navigazione corrispondente è Course.The CourseID property is a foreign key, and the corresponding navigation property is Course. Un'entità Enrollment è associata a un'entità Course.An Enrollment entity is associated with one Course entity.

Entity Framework interpretata una proprietà come proprietà di chiave esterna se è denominata <navigation property name><primary key property name>, ad esempio StudentID per la proprietà di navigazione Student poiché la chiave primaria dell'entità Student è ID.Entity Framework interprets a property as a foreign key property if it's named <navigation property name><primary key property name> (for example, StudentID for the Student navigation property since the Student entity's primary key is ID). Le proprietà di una chiave esterna possono anche essere denominate semplicemente <primary key property name>, ad esempio CourseID poiché la chiave primaria dell'entità Course è CourseID.Foreign key properties can also be named simply <primary key property name> (for example, CourseID since the Course entity's primary key is CourseID).

Entità Course (Corso)The Course entity

Diagramma entità Course (Corso)

Nella cartella Models creare Course.cs e sostituire il codice esistente con il codice seguente:In the Models folder, create Course.cs and replace the existing code with the following code:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

La proprietà Enrollments rappresenta una proprietà di navigazione.The Enrollments property is a navigation property. È possibile correlare un'entità Course a un numero qualsiasi di entità Enrollment.A Course entity can be related to any number of Enrollment entities.

Altre informazioni sull'attributo DatabaseGenerated sono disponibili nell'esercitazione successiva di questa serie.We'll say more about the DatabaseGenerated attribute in a later tutorial in this series. In pratica, questo attributo consente di immettere la chiave primaria per il corso invece di essere generata dal database.Basically, this attribute lets you enter the primary key for the course rather than having the database generate it.

Creare il contesto di databaseCreate the database context

La classe del contesto di database è la classe principale che coordina le funzionalità di Entity Framework per un determinato modello di dati.The main class that coordinates Entity Framework functionality for a given data model is the database context class. Questa classe viene creata mediante derivazione dalla classe Microsoft.EntityFrameworkCore.DbContext.You create this class by deriving from the Microsoft.EntityFrameworkCore.DbContext class. Nel codice vengono specificate le entità incluse nel modello di dati.In your code you specify which entities are included in the data model. È anche possibile personalizzare un determinato comportamento di Entity Framework.You can also customize certain Entity Framework behavior. In questo progetto la classe è denominata SchoolContext.In this project, the class is named SchoolContext.

Creare una cartella denominata Data (Dati) nella cartella del progetto.In the project folder, create a folder named Data.

Nella cartella Data (Dati) creare un file di classe denominato SchoolContext.cs e sostituire il codice del modello con il codice seguente:In the Data folder create a new class file named SchoolContext.cs, and replace the template code with the following code:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }
    }
}

Questo codice crea una proprietà DbSet per ogni set di entità.This code creates a DbSet property for each entity set. Nella terminologia di Entity Framework, un set di entità corrisponde in genere alla tabella di un database e un'entità corrisponde a una riga della tabella.In Entity Framework terminology, an entity set typically corresponds to a database table, and an entity corresponds to a row in the table.

Se sono state omesse le istruzioni DbSet<Enrollment> e DbSet<Course>, potrebbe comunque funzionare.You could've omitted the DbSet<Enrollment> and DbSet<Course> statements and it would work the same. Entity Framework le include in modo implicito perché l'entità Student fa riferimento all'entità Enrollment e l'entità Enrollment fa riferimento all'entità Course.The Entity Framework would include them implicitly because the Student entity references the Enrollment entity and the Enrollment entity references the Course entity.

Quando viene creato il database, Entity Framework crea tabelle i cui nomi sono gli stessi della proprietà DbSet.When the database is created, EF creates tables that have names the same as the DbSet property names. I nomi di proprietà per le raccolte sono generalmente usati al plurale (Students anziché Student). Gli sviluppatori non hanno tuttavia un'opinione unanime sul fatto che i nomi di tabella debbano essere usati al plurale.Property names for collections are typically plural (Students rather than Student), but developers disagree about whether table names should be pluralized or not. Per queste esercitazioni, viene eseguito l'override del comportamento predefinito specificando nomi di tabella al singolare in DbContext.For these tutorials you'll override the default behavior by specifying singular table names in the DbContext. A tale scopo, aggiungere il codice evidenziato seguente dopo l'ultima proprietà DbSet.To do that, add the following highlighted code after the last DbSet property.

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Course>().ToTable("Course");
            modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
            modelBuilder.Entity<Student>().ToTable("Student");
        }
    }
}

Registrare SchoolContextRegister the SchoolContext

ASP.NET Core implementa l'inserimento delle dipendenze per impostazione predefinita.ASP.NET Core implements dependency injection by default. I servizi, ad esempio il contesto di database di Entity Framework, vengono registrati con l'inserimento delle dipendenze durante l'avvio dell'applicazione.Services (such as the EF database context) are registered with dependency injection during application startup. Questi servizi vengono quindi offerti ai componenti per cui sono necessari (ad esempio i controller MVC) tramite i parametri del costruttore.Components that require these services (such as MVC controllers) are provided these services via constructor parameters. Il codice del costruttore del controller che ottiene un'istanza di contesto viene illustrato più avanti in questa esercitazione.You'll see the controller constructor code that gets a context instance later in this tutorial.

Per registrare SchoolContext come servizio, aprire Startup.cs e aggiungere le righe evidenziate al metodo ConfigureServices.To register SchoolContext as a service, open Startup.cs, and add the highlighted lines to the ConfigureServices method.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<SchoolContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddMvc();
}

Il nome della stringa di connessione viene passato al contesto chiamando un metodo in un oggetto DbContextOptionsBuilder.The name of the connection string is passed in to the context by calling a method on a DbContextOptionsBuilder object. Per lo sviluppo locale, il sistema di configurazione di ASP.NET Core legge la stringa di connessione dal file appsettings.json.For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Aggiungere le istruzioni using per gli spazi dei nomi ContosoUniversity.Data e Microsoft.EntityFrameworkCore, quindi compilare il progetto.Add using statements for ContosoUniversity.Data and Microsoft.EntityFrameworkCore namespaces, and then build the project.

using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;

Aprire il file appsettings.json e aggiungere una stringa di connessione come illustrato nel codice seguente.Open the appsettings.json file and add a connection string as shown in the following example.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

LocalDB di SQL Server ExpressSQL Server Express LocalDB

La stringa di connessione specifica un database Local DB di SQL Server.The connection string specifies a SQL Server LocalDB database. Local DB è una versione leggera del motore di database di SQL Server Express appositamente pensato per lo sviluppo di applicazioni e non per la produzione.LocalDB is a lightweight version of the SQL Server Express Database Engine and is intended for application development, not production use. Local DB viene avviato su richiesta ed eseguito in modalità utente; non richiede quindi una configurazione complessa.LocalDB starts on demand and runs in user mode, so there's no complex configuration. Per impostazione predefinita, Local DB crea file di database con estensione mdf nella directory C:/Users/<user>.By default, LocalDB creates .mdf database files in the C:/Users/<user> directory.

Inizializzare il database con dati di testInitialize DB with test data

Entity Framework creerà un database vuoto.The Entity Framework will create an empty database for you. In questa sezione viene scritto un metodo che viene chiamato dopo aver creato il database al fine di popolare il database con i dati di test.In this section, you write a method that's called after the database is created in order to populate it with test data.

Per creare automaticamente il database, viene usato il metodo EnsureCreated.Here you'll use the EnsureCreated method to automatically create the database. In un'esercitazione successiva viene spiegato come gestire le modifiche al modello usando Migrazioni Code First, che consente di modificare lo schema del database anziché dover eliminare e ricreare il database.In a later tutorial you'll see how to handle model changes by using Code First Migrations to change the database schema instead of dropping and re-creating the database.

Nella cartella Data (Dati) creare un file di classe denominato DbInitializer.cs e sostituire il codice del modello con il codice seguente. Verrà creato un database se necessario e i dati di test saranno caricati nel nuovo database.In the Data folder, create a new class file named DbInitializer.cs and replace the template code with the following code, which causes a database to be created when needed and loads test data into the new database.

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Data
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            context.Database.EnsureCreated();

            // Look for any students.
            if (context.Students.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
            new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
            new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
            };
            foreach (Student s in students)
            {
                context.Students.Add(s);
            }
            context.SaveChanges();

            var courses = new Course[]
            {
            new Course{CourseID=1050,Title="Chemistry",Credits=3},
            new Course{CourseID=4022,Title="Microeconomics",Credits=3},
            new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
            new Course{CourseID=1045,Title="Calculus",Credits=4},
            new Course{CourseID=3141,Title="Trigonometry",Credits=4},
            new Course{CourseID=2021,Title="Composition",Credits=3},
            new Course{CourseID=2042,Title="Literature",Credits=4}
            };
            foreach (Course c in courses)
            {
                context.Courses.Add(c);
            }
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
            new Enrollment{StudentID=3,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
            new Enrollment{StudentID=6,CourseID=1045},
            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };
            foreach (Enrollment e in enrollments)
            {
                context.Enrollments.Add(e);
            }
            context.SaveChanges();
        }
    }
}

Il codice verifica l'esistenza di studenti nel database. In caso negativo presuppone che il database sia nuovo e che sia necessario eseguire l'inizializzazione con i dati di test.The code checks if there are any students in the database, and if not, it assumes the database is new and needs to be seeded with test data. I dati di test vengono caricati in matrici anziché in raccolte List<T> per ottimizzare le prestazioni.It loads test data into arrays rather than List<T> collections to optimize performance.

In Program.cs modificare il metodo Main per eseguire le operazioni seguenti all'avvio dell'applicazione:In Program.cs, modify the Main method to do the following on application startup:

  • Ottenere un'istanza del contesto di database dal contenitore di inserimento delle dipendenze.Get a database context instance from the dependency injection container.
  • Chiamare il metodo di inizializzazione, passandolo al contesto.Call the seed method, passing to it the context.
  • Eliminare il contesto dopo che il metodo di inizializzazione è stato completato.Dispose the context when the seed method is done.
public static void Main(string[] args)
{
     var host = CreateWebHostBuilder(args).Build();

    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<SchoolContext>();
            DbInitializer.Initialize(context);
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while seeding the database.");
        }
    }

    host.Run();
}

Aggiungere le istruzioni using:Add using statements:

using Microsoft.Extensions.DependencyInjection;
using ContosoUniversity.Data;

Nelle esercitazioni precedenti il codice nel metodo Configure in Startup.cs può essere simile.In older tutorials, you may see similar code in the Configure method in Startup.cs. È consigliabile usare il metodo Configure solo per impostare la pipeline delle richieste.We recommend that you use the Configure method only to set up the request pipeline. Il codice di avvio dell'applicazione fa parte del metodo Main.Application startup code belongs in the Main method.

A questo punto l'applicazione viene eseguita per la prima volta. Il database viene creato e inizializzato con i dati di test.Now the first time you run the application, the database will be created and seeded with test data. Ogni volta che si modifica il modello di dati, è possibile eliminare il database, aggiornare il metodo di inizializzazione e ricominciare con un nuovo database allo stesso modo.Whenever you change your data model, you can delete the database, update your seed method, and start afresh with a new database the same way. Nelle esercitazioni successive viene illustrato come modificare il database alla modifica del modello di dati, senza eliminare e ricreare il database.In later tutorials, you'll see how to modify the database when the data model changes, without deleting and re-creating it.

Creare controller e visualizzazioniCreate controller and views

A questo punto viene usato il motore di scaffolding in Visual Studio per aggiungere un controller MVC e le visualizzazioni che saranno usate da Entity Framework per eseguire le query e salvare i dati.Next, you'll use the scaffolding engine in Visual Studio to add an MVC controller and views that will use EF to query and save data.

La creazione automatica di metodi di azione CRUD e di visualizzazioni è nota come scaffolding.The automatic creation of CRUD action methods and views is known as scaffolding. Lo scaffolding differisce dalla generazione di codice in quanto il codice di scaffolding è un punto di partenza modificabile per essere adattato ai propri requisiti, mentre generalmente il codice generato non viene modificato.Scaffolding differs from code generation in that the scaffolded code is a starting point that you can modify to suit your own requirements, whereas you typically don't modify generated code. Quando è necessario personalizzare il codice generato, usare classi parziali oppure rigenerare il codice in caso di modifiche.When you need to customize generated code, you use partial classes or you regenerate the code when things change.

  • Fare clic con il pulsante destro del mouse sulla cartella Controller in Esplora soluzioni e scegliere Aggiungi -> Nuovo elemento di scaffolding.Right-click the Controllers folder in Solution Explorer and select Add > New Scaffolded Item.

  • Nella finestra di dialogo Aggiungi scaffolding eseguire le operazioni seguenti:In the Add Scaffold dialog box:

    • Selezionare Controller MVC con visualizzazioni, che usa Entity Framework.Select MVC controller with views, using Entity Framework.

    • Fare clic su Aggiungi.Click Add. Verrà visualizzata la finestra di dialogo Aggiungi Controller MVC con visualizzazioni, che usa Entity Framework.The Add MVC Controller with views, using Entity Framework dialog box appears.

      Scaffolding di Student

    • In Classe modello selezionare Student (Studente).In Model class select Student.

    • In Classe contesto di dati selezionare SchoolContext.In Data context class select SchoolContext.

    • Accettare il valore predefinito StudentsController come nome.Accept the default StudentsController as the name.

    • Fare clic su Aggiungi.Click Add.

    Quando si fa clic su Aggiungi, il motore di scaffolding di Visual Studio crea un file StudentsController.cs e un set di visualizzazioni (file con estensione cshtml) che vengono usate insieme al controller.When you click Add, the Visual Studio scaffolding engine creates a StudentsController.cs file and a set of views (.cshtml files) that work with the controller.

Il motore di scaffolding può anche creare il contesto del database se non è stato precedentemente creato in modo manuale, come all'inizio di questa esercitazione.(The scaffolding engine can also create the database context for you if you don't create it manually first as you did earlier for this tutorial. È possibile specificare una nuova classe di contesto nella casella Aggiungi controller facendo clic sul segno + a destra della casella di Classe contesto di dati.You can specify a new context class in the Add Controller box by clicking the plus sign to the right of Data context class. Visual Studio creerà quindi la classe DbContext nonché il controller e le visualizzazioni.Visual Studio will then create your DbContext class as well as the controller and views.)

Si noti che il controller usa SchoolContext come parametro del costruttore.You'll notice that the controller takes a SchoolContext as a constructor parameter.

namespace ContosoUniversity.Controllers
{
    public class StudentsController : Controller
    {
        private readonly SchoolContext _context;

        public StudentsController(SchoolContext context)
        {
            _context = context;
        }

L'inserimento delle dipendenze di ASP.NET Core si occupa di passare un'istanza di SchoolContext al controller.ASP.NET Core dependency injection takes care of passing an instance of SchoolContext into the controller. Tale comportamento è configurato nel file Startup.cs in precedenza.You configured that in the Startup.cs file earlier.

Il controller contiene un metodo di azione Index che consente di visualizzare tutti gli studenti nel database.The controller contains an Index action method, which displays all students in the database. Il metodo ottiene un elenco degli studenti dal set di entità Students (Studenti) leggendo la proprietà Students dell'istanza del contesto di database:The method gets a list of students from the Students entity set by reading the Students property of the database context instance:

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}

Gli elementi di programmazione asincrona in questo codice vengono illustrati più avanti nell'esercitazione.You'll learn about the asynchronous programming elements in this code later in the tutorial.

Nella visualizzazione Views/Students/Index.cshtml è contenuto l'elenco sotto forma di tabella:The Views/Students/Index.cshtml view displays this list in a table:

@model IEnumerable<ContosoUniversity.Models.Student>

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
                <th>
                    @Html.DisplayNameFor(model => model.LastName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.FirstMidName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.EnrollmentDate)
                </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.ID">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

Premere CTRL+F5 per eseguire il progetto oppure selezionare Debug > Avvia senza eseguire debug dal menu.Press CTRL+F5 to run the project or choose Debug > Start Without Debugging from the menu.

Fare clic sulla scheda Students (Studenti) per visualizzare i dati di test inseriti nel metodo DbInitializer.Initialize.Click the Students tab to see the test data that the DbInitializer.Initialize method inserted. A seconda delle dimensione della finestra del browser, il collegamento della scheda Students viene visualizzato in alto alla pagina oppure è necessario selezionare l'icona di spostamento in alto a destra per visualizzarlo.Depending on how narrow your browser window is, you'll see the Students tab link at the top of the page or you'll have to click the navigation icon in the upper right corner to see the link.

Home page di Contoso University ristretta

Pagina Student Index (Indice degli studenti)

Visualizzare il databaseView the database

Dopo aver avviato l'applicazione, il metodo DbInitializer.Initialize chiama EnsureCreated.When you started the application, the DbInitializer.Initialize method calls EnsureCreated. Entity Framework ha verificato che non esiste un database e ne ha pertanto creato uno. La parte restante di codice del metodo Initialize ha popolato il database con i dati.EF saw that there was no database and so it created one, then the remainder of the Initialize method code populated the database with data. È possibile usare Esplora oggetti di SQL Server per visualizzare il database in Visual Studio.You can use SQL Server Object Explorer (SSOX) to view the database in Visual Studio.

Chiudere il browser.Close the browser.

Se la finestra di Esplora oggetti di SQL Server non è già aperta, selezionarla dal menu Visualizza in Visual Studio.If the SSOX window isn't already open, select it from the View menu in Visual Studio.

In Esplora oggetti di SQL Server fare clic su (localdb) \MSSQLLocalDB > Database e fare clic sulla voce che corrisponde al nome del database contenuto nella stringa di connessione nel file appsettings.json.In SSOX, click (localdb)\MSSQLLocalDB > Databases, and then click the entry for the database name that's in the connection string in your appsettings.json file.

Espandere il nodo Tabelle per visualizzare le tabelle nel database.Expand the Tables node to see the tables in your database.

Tabelle in Esplora oggetti di SQL Server

Fare clic con il pulsante destro del mouse sulla tabella Student (Studente) e fare clic su Visualizza dati per visualizzare le colonne create e le righe inserite nella tabella.Right-click the Student table and click View Data to see the columns that were created and the rows that were inserted into the table.

Tabella Student (Studente) in Esplora oggetti di SQL Server

I file di database con estensione mdf e ldf sono contenuti nella cartella C:\Utenti\<nomeutente> .The .mdf and .ldf database files are in the C:\Users\<yourusername> folder.

Poiché si sta chiamando EnsureCreated nel metodo di inizializzatore che viene eseguito all'avvio dell'app, è ora possibile modificare la classe Student, eliminare il database ed eseguire nuovamente l'applicazione. Il database sarà automaticamente ricreato e rispecchierà la modifica.Because you're calling EnsureCreated in the initializer method that runs on app start, you could now make a change to the Student class, delete the database, run the application again, and the database would automatically be re-created to match your change. Ad esempio, se si aggiunge una proprietà EmailAddress alla classe Student, una nuova colonna EmailAddress sarà visualizzata nella tabella ricreata.For example, if you add an EmailAddress property to the Student class, you'll see a new EmailAddress column in the re-created table.

ConvenzioniConventions

Grazie all'uso di convenzioni o di ipotesi di Entity Framework, la quantità di codice scritto che è necessario a Entity Framework per creare un database completo è minino.The amount of code you had to write in order for the Entity Framework to be able to create a complete database for you is minimal because of the use of conventions, or assumptions that the Entity Framework makes.

  • I nomi delle proprietà DbSet vengono usate come nomi di tabella.The names of DbSet properties are used as table names. Per le entità a cui non fa riferimento una proprietà DbSet, i nomi della classe di entità vengono usati come nome di tabella.For entities not referenced by a DbSet property, entity class names are used as table names.

  • I nomi della proprietà di entità vengono usati come nomi di colonna.Entity property names are used for column names.

  • Le proprietà dell'entità vengono denominate ID o classnameID e vengono riconosciute come proprietà della chiave primaria.Entity properties that are named ID or classnameID are recognized as primary key properties.

  • Una proprietà viene interpretata come proprietà di una chiave esterna se è denominata <nome della proprietà di navigazione><nome della proprietà della chiave primaria> , ad esempio StudentID per la proprietà di navigazione Student poiché la chiave primaria dell'entità Student è ID.A property is interpreted as a foreign key property if it's named <navigation property name><primary key property name> (for example, StudentID for the Student navigation property since the Student entity's primary key is ID). Le proprietà di una chiave esterna possono anche essere denominate semplicemente <nome della proprietà della chiave primaria> , ad esempio EnrollmentID poiché la chiave primaria dell'entità Enrollment è EnrollmentID.Foreign key properties can also be named simply <primary key property name> (for example, EnrollmentID since the Enrollment entity's primary key is EnrollmentID).

È possibile eseguire l'override del comportamento convenzionale.Conventional behavior can be overridden. Ad esempio, è possibile specificare in modo esplicito i nomi di tabella, come illustrato in precedenza in questa esercitazione.For example, you can explicitly specify table names, as you saw earlier in this tutorial. È anche possibile impostare i nomi delle colonne e impostare qualsiasi proprietà come chiave primaria o chiave esterna, come sarà spiegato in un'esercitazione successiva di questa serie.And you can set column names and set any property as primary key or foreign key, as you'll see in a later tutorial in this series.

Codice asincronoAsynchronous code

La programmazione asincrona è la modalità predefinita per ASP.NET Core ed Entity Framework Core.Asynchronous programming is the default mode for ASP.NET Core and EF Core.

Per un server Web è disponibile un numero limitato di thread e in situazioni di carico elevato tutti i thread disponibili potrebbero essere in uso.A web server has a limited number of threads available, and in high load situations all of the available threads might be in use. In queste circostanze il server non può elaborare nuove richieste finché i thread non saranno liberi.When that happens, the server can't process new requests until the threads are freed up. Con il codice sincrono, può succedere che molti thread siano vincolati nonostante in quel momento non stiano eseguendo alcuna operazione. Rimangono tuttavia in attesa che l'operazione I/O sia completata.With synchronous code, many threads may be tied up while they aren't actually doing any work because they're waiting for I/O to complete. Con il codice asincrono, se un processo è in attesa del completamento dell'operazione I/O, il thread viene liberato e il server lo può usare per l'elaborazione di altre richieste.With asynchronous code, when a process is waiting for I/O to complete, its thread is freed up for the server to use for processing other requests. Di conseguenza, il codice asincrono consente un uso più efficiente delle risorse e il server è abilitato per gestire una maggiore quantità di traffico senza ritardi.As a result, asynchronous code enables server resources to be used more efficiently, and the server is enabled to handle more traffic without delays.

Il codice asincrono comporta un minimo sovraccarico in fase di esecuzione. In caso di traffico ridotto, il calo delle prestazioni è irrilevante, mentre nelle situazioni di traffico elevato, è essenziale ottimizzare le prestazioni potenziali.Asynchronous code does introduce a small amount of overhead at run time, but for low traffic situations the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.

Nel codice seguente la parola chiave async, il valore restituito Task<T>, la parola chiave await e il metodo ToListAsync consentono di eseguire il codice in modo asincrono.In the following code, the async keyword, Task<T> return value, await keyword, and ToListAsync method make the code execute asynchronously.

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}
  • La parola chiaveasync indica al compilatore di generare callback per parti del corpo del metodo e di creare automaticamente l'oggetto Task<IActionResult> restituito.The async keyword tells the compiler to generate callbacks for parts of the method body and to automatically create the Task<IActionResult> object that's returned.

  • Il tipo restituito Task<IActionResult> rappresenta il lavoro in corso con un risultato di tipo IActionResult.The return type Task<IActionResult> represents ongoing work with a result of type IActionResult.

  • La parola chiave await indica al compilatore di suddividere il metodo in due parti.The await keyword causes the compiler to split the method into two parts. La prima parte termina con l'operazione avviata in modo asincrono.The first part ends with the operation that's started asynchronously. La seconda parte viene inserita in un metodo di callback che viene chiamato al termine dell'operazione.The second part is put into a callback method that's called when the operation completes.

  • ToListAsync è la versione asincrona del metodo di estensione ToList.ToListAsync is the asynchronous version of the ToList extension method.

Alcuni aspetti da considerare quando si scrive codice asincrono usato da Entity Framework:Some things to be aware of when you are writing asynchronous code that uses the Entity Framework:

  • Solo le istruzioni che generano query o comandi da inviare al database vengono eseguite in modo asincrono,Only statements that cause queries or commands to be sent to the database are executed asynchronously. ad esempio ToListAsync, SingleOrDefaultAsync, e SaveChangesAsync.That includes, for example, ToListAsync, SingleOrDefaultAsync, and SaveChangesAsync. Non sono incluse le istruzioni che modificano solo un oggetto IQueryable, ad esempio var students = context.Students.Where(s => s.LastName == "Davolio").It doesn't include, for example, statements that just change an IQueryable, such as var students = context.Students.Where(s => s.LastName == "Davolio").

  • Un contesto di Entity Framework non è thread-safe. Non tentare di eseguire più operazioni parallelamente.An EF context isn't thread safe: don't try to do multiple operations in parallel. Quando si chiama un metodo asincrono Entity Framework, usare sempre la parola chiave await.When you call any async EF method, always use the await keyword.

  • Se si vogliono sfruttare i vantaggi del codice asincrono in termini di prestazioni, verificare che i pacchetti della libreria impiegati, ad esempio per il paging, usino la modalità asincrona per chiamare i metodi di Entity Framework che generano query da inviare al database.If you want to take advantage of the performance benefits of async code, make sure that any library packages that you're using (such as for paging), also use async if they call any Entity Framework methods that cause queries to be sent to the database.

Per altre informazioni sulla programmazione asincrona in .NET, vedere Panoramica della programmazione asincrona.For more information about asynchronous programming in .NET, see Async Overview.

Ottenere il codiceGet the code

Scaricare o visualizzare l'applicazione completata.Download or view the completed application.

Passaggi successiviNext steps

Le attività di questa esercitazione sono le seguenti:In this tutorial, you:

  • Creare un'app Web ASP.NET Core MVCCreated ASP.NET Core MVC web app
  • Impostare lo stile del sitoSet up the site style
  • Scoprire di più sui pacchetti NuGet di EF CoreLearned about EF Core NuGet packages
  • Creare il modello di datiCreated the data model
  • Creare il contesto del databaseCreated the database context
  • Registrare SchoolContextRegistered the SchoolContext
  • Inizializzare il database con dati di testInitialized DB with test data
  • Creare controller e visualizzazioniCreated controller and views
  • Visualizzare il databaseViewed the database

Nella prossima esercitazione vengono esaminate le operazioni CRUD per creare, leggere, aggiornare, eliminare ed elencare.In the following tutorial, you'll learn how to perform basic CRUD (create, read, update, delete) operations.

Passare all'esercitazione successiva per informazioni su come eseguire operazioni CRUD (creazione, lettura, aggiornamento ed eliminazione) di base.Advance to the next tutorial to learn how to perform basic CRUD (create, read, update, delete) operations.