Razor Pages mit Entity Framework Core in ASP.NET Core – Tutorial 1 bis 8Razor Pages with Entity Framework Core in ASP.NET Core - Tutorial 1 of 8

Von Tom Dykstra und Rick AndersonBy Tom Dykstra and Rick Anderson

Dies ist das erste einer Reihe von Tutorials, die zeigen, wie Entity Framework (EF) Core für eine Razor Pages-App mit ASP.NET Core verwendet wird.This is the first in a series of tutorials that show how to use Entity Framework (EF) Core in an ASP.NET Core Razor Pages app. In den Tutorials wird eine Website für eine fiktive Contoso University erstellt.The tutorials build a web site for a fictional Contoso University. Sie enthält Funktionen wie die Zulassung von Studenten, die Erstellung von Kursen und Aufgaben von Dozenten.The site includes functionality such as student admission, course creation, and instructor assignments. In diesem Tutorial wird der Code-First-Ansatz verwendet.The tutorial uses the code first approach. Informationen zum Durcharbeiten dieses Tutorials mit dem Database-First-Ansatz finden Sie in diesem GitHub-Issue.For information on following this tutorial using the database first approach, see this Github issue.

Download or view the completed app (Herunterladen oder anzeigen der vollständigen App).Download or view the completed app. Anweisungen zum Download.Download instructions.

VoraussetzungenPrerequisites

Datenbank-EnginesDatabase engines

Die Visual Studio-Anweisungen verwenden SQL Server LocalDB, eine Version von SQL Server Express, die nur unter Windows ausgeführt werden kann.The Visual Studio instructions use SQL Server LocalDB, a version of SQL Server Express that runs only on Windows.

In den Visual Studio Code-Anweisungen wird SQLite verwendet, eine plattformübergreifende Datenbank-Engine.The Visual Studio Code instructions use SQLite, a cross-platform database engine.

Wenn Sie SQLite verwenden möchten, laden Sie ein Drittanbietertool zum Verwalten und Anzeigen einer SQLite-Datenbank (z.B. DB Browser für SQLite) herunter, und installieren Sie es.If you choose to use SQLite, download and install a third-party tool for managing and viewing a SQLite database, such as DB Browser for SQLite.

ProblembehandlungTroubleshooting

Wenn Sie auf ein Problem stoßen, das Sie nicht lösen können, vergleichen Sie Ihren den Code mit dem vollständigen Projekt.If you run into a problem you can't resolve, compare your code to the completed project. Eine gute Möglichkeit, Hilfe zu erhalten, besteht darin, eine Frage auf StackOverflow.com zu stellen und dabei das ASP.NET Core-Tag oder das EF Core-Tag zu verwenden.A good way to get help is by posting a question to StackOverflow.com, using the ASP.NET Core tag or the EF Core tag.

Die Beispiel-AppThe sample app

Bei der App, die mithilfe dieser Tutorials erstellt werden soll, handelt es sich um eine einfache Website einer Universität.The app built in these tutorials is a basic university web site. Benutzer können Informationen zu den Studenten, Kursen und Dozenten abrufen.Users can view and update student, course, and instructor information. Im Folgenden sind einige Anzeigen dargestellt, die mithilfe dieses Tutorials erstellt werden.Here are a few of the screens created in the tutorial.

Indexseite „Studenten“

Bearbeitungsseite für Studenten

Der Benutzeroberflächenstil dieser Website basiert auf den integrierten Projektvorlagen.The UI style of this site is based on the built-in project templates. Das Tutorial konzentriert sich auf die Verwendung von EF Core mit ASP.NET Core und nicht auf die Anpassung der Benutzeroberfläche.The tutorial's focus is on how to use EF Core with ASP.NET Core, not how to customize the UI.

Erstellen des Web-App-ProjektsCreate the web app project

  1. Starten Sie Visual Studio, und wählen Sie Neues Projekt erstellen aus.Start Visual Studio and select Create a new project.
  2. Wählen Sie im Dialogfeld Neues Projekt die Option ASP.NET Core-Webanwendung > Weiter aus.In the Create a new project dialog, select ASP.NET Core Web Application > Next.
  3. Geben Sie ContosoUniversity im Dialogfeld Neues Projekt konfigurieren für Projektname ein.In the Configure your new project dialog, enter ContosoUniversity for Project name. Es ist wichtig, genau diesen Namen unter Berücksichtigung der Groß-/Kleinschreibung zu verwenden, sodass beim Kopieren von Code jeder namespace übereinstimmt.It's important to use this exact name including capitalization, so each namespace matches when code is copied.
  4. Klicken Sie auf Erstellen.Select Create.
  5. Wählen Sie im Dialogfeld Neue ASP.NET Core-Webanwendung erstellen Folgendes aus:In the Create a new ASP.NET Core web application dialog, select:
    1. In den Dropdownmenüs .NET Core und ASP.NET Core 5.0..NET Core and ASP.NET Core 5.0 in the dropdowns.
    2. ASP.NET Core-Web-App (Model View Controller) .ASP.NET Core Web App (Model-View-Controller).
    3. Dialogfeld Neues ASP.NET Core-Projekt erstellenCreate New ASP.NET Core Project dialog

Einrichten des WebsitestilsSet up the site style

Kopieren Sie den folgenden Code, und fügen Sie ihn in die Datei Pages/Shared/_Layout.cshtml ein: Copy and paste the following code into the Pages/Shared/_Layout.cshtml file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Contoso University</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <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-page="/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-page="/About">About</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">Students</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Courses/Index">Courses</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Instructors/Index">Instructors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Departments/Index">Departments</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2020 - Contoso University - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

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

Mit der Layoutdatei werden die Kopfzeile, die Fußzeile und das Menü der Website festgelegt.The layout file sets the site header, footer, and menu. Durch den vorangehenden Code werden folgende Änderungen vorgenommen:The preceding code makes the following changes:

  • Jedes Vorkommen von „ContosoUniversity“ wird in „Contoso University“ geändert.Each occurrence of "ContosoUniversity" to "Contoso University". Diese Begriffskombination kommt dreimal vor.There are three occurrences.
  • Die Menüeinträge Home und Privacy werden gelöscht.The Home and Privacy menu entries are deleted.
  • Es werden Einträge für About, Students, Courses, Instructors und Departmens hinzugefügt.Entries are added for About, Students, Courses, Instructors, and Departments.

Ersetzen Sie den Inhalt der Datei Pages/Index.cshtml durch den folgenden Code:In Pages/Index.cshtml, replace the contents of the file with the following code:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="row mb-auto">
    <div class="col-md-4">
        <div class="row no-gutters border mb-4">
            <div class="col p-4 mb-4 ">
                <p class="card-text">
                    Contoso University is a sample application that
                    demonstrates how to use Entity Framework Core in an
                    ASP.NET Core Razor Pages web app.
                </p>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="row no-gutters border mb-4">
            <div class="col p-4 d-flex flex-column position-static">
                <p class="card-text mb-auto">
                    You can build the application by following the steps in a series of tutorials.
                </p>
                <p>
                    <a href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro" class="stretched-link">See the tutorial</a>
                </p>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="row no-gutters border mb-4">
            <div class="col p-4 d-flex flex-column">
                <p class="card-text mb-auto">
                    You can download the completed project from GitHub.
                </p>
                <p>
                    <a href="https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-rp/intro/samples" class="stretched-link">See project source code</a>
                </p>
            </div>
        </div>
    </div>
</div>

Der obige Code ersetzt den Text über ASP.NET Core durch Text über diese App.The preceding code replaces the text about ASP.NET Core with text about this app.

Führen Sie die App aus, um sicherzustellen, dass die Startseite angezeigt wird.Run the app to verify that the home page appears.

Das DatenmodellThe data model

In den folgenden Abschnitten wird ein Datenmodell erstellt:The following sections create a data model:

Datenmodelldiagramm zur Kursanmeldung für Studenten

Ein Student kann für beliebig viele Kurse angemeldet sein, und für jeden Kurs kann eine beliebige Anzahl von Studenten angemeldet sein.A student can enroll in any number of courses, and a course can have any number of students enrolled in it.

Die Entität „Student“The Student entity

Entitätsdiagramm „Student“

  • Erstellen Sie im Projektordner den Ordner Models.Create a Models folder in the project folder.

  • Erstellen Sie Models/Student.cs mit folgendem Code:Create Models/Student.cs 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; }
        }
    }
    

Die ID-Eigenschaft fungiert als Primärschlüsselspalte der Datenbanktabelle, die diesem Kurs entspricht.The ID property becomes the primary key column of the database table that corresponds to this class. Standardmäßig interpretiert Entity Framework Core eine Eigenschaft mit dem Namen ID oder classnameID als Primärschlüssel.By default, EF Core interprets a property that's named ID or classnameID as the primary key. Der alternative, automatisch erkannte Name für den Primärschlüssel der Klasse Student lautet also StudentID.So the alternative automatically recognized name for the Student class primary key is StudentID. Weitere Informationen finden Sie unter EF Core – Schlüssel.For more information, see EF Core - Keys.

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft.The Enrollments property is a navigation property. Navigationseigenschaften enthalten andere Entitäten, die dieser Entität zugehörig sind.Navigation properties hold other entities that are related to this entity. In diesem Fall enthält die Enrollments-Eigenschaft einer Student-Entität alle Enrollment-Entitäten, die mit diesem Studenten in Zusammenhang stehen.In this case, the Enrollments property of a Student entity holds all of the Enrollment entities that are related to that Student. Wenn es z.B. für eine „Student“-Zeile in der Datenbank zwei zugehörige „Enrollment“-Zeilen gibt, enthält die Navigationseigenschaft Enrollments zwei Enrollment-Entitäten.For example, if a Student row in the database has two related Enrollment rows, the Enrollments navigation property contains those two Enrollment entities.

In der-Datenbank ist eine Enrollment-Zeile mit einer Student-Zeile verknüpft, wenn die StudentID-Spalte den ID-Wert des Studenten enthält.In the database, an Enrollment row is related to a Student row if its StudentID column contains the student's ID value. Angenommen, eine Student-Zeile weist die ID=1 auf.For example, suppose a Student row has ID=1. Zugehörige Enrollment-Zeilen weisen die StudentID = 1 auf.Related Enrollment rows will have StudentID = 1. StudentID ist ein Fremdschlüssel in der Enrollment-Tabelle.StudentID is a foreign key in the Enrollment table.

Die Enrollments-Eigenschaft wird als ICollection<Enrollment> definiert, da es möglicherweise mehrere zugehörige Enrollment-Entitäten gibt.The Enrollments property is defined as ICollection<Enrollment> because there may be multiple related Enrollment entities. Sie können andere Sammlungstypen verwenden, z.B. List<Enrollment> oder HashSet<Enrollment>.You can use other collection types, such as List<Enrollment> or HashSet<Enrollment>. Wenn ICollection<Enrollment> verwendet wird, erstellt Entity Framework Core standardmäßig eine HashSet<Enrollment>-Auflistung.When ICollection<Enrollment> is used, EF Core creates a HashSet<Enrollment> collection by default.

Die Entität „Enrollment“The Enrollment entity

Entitätsdiagramm „Enrollment“

Erstellen Sie Models/Enrollment.cs mit folgendem Code:Create Models/Enrollment.cs 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; }
    }
}

Die EnrollmentID-Eigenschaft ist der Primärschlüssel. Diese Entität verwendet das classnameID-Muster anstelle nur der ID.The EnrollmentID property is the primary key; this entity uses the classnameID pattern instead of ID by itself. Wählen Sie für ein Produktionsdatenmodell ein Muster aus, und verwenden Sie es einheitlich.For a production data model, choose one pattern and use it consistently. In diesem Tutorial werden beide Muster verwendet, um zu veranschaulichen, dass beide funktionieren.This tutorial uses both just to illustrate that both work. Wenn Sie ID ohne classname verwenden, ist es einfacher, einige Arten von Datenmodelländerungen zu implementieren.Using ID without classname makes it easier to implement some kinds of data model changes.

Bei der Grade-Eigenschaft handelt es sich um eine enum.The Grade property is an enum. Das Fragezeichen nach der Grade-Typdeklaration gibt an, dass die Grade-Eigenschaft NULL-Werte zulässt.The question mark after the Grade type declaration indicates that the Grade property is nullable. Eine Grade-Eigenschaft mit dem Wert NULL unterscheidet sich von einer Grade-Eigenschaft mit dem Wert 0 (null): Der Wert NULL bedeutet, dass keine Grade-Eigenschaft bekannt ist oder noch keine zugewiesen wurde.A grade that's null is different from a zero grade—null means a grade isn't known or hasn't been assigned yet.

Bei der StudentID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Student ist die entsprechende Navigationseigenschaft.The StudentID property is a foreign key, and the corresponding navigation property is Student. Die Enrollment-Entität wird einer Student-Entität zugewiesen. Das bedeutet, dass die Eigenschaft genau eine Student-Entität enthält.An Enrollment entity is associated with one Student entity, so the property contains a single Student entity.

Bei der CourseID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Course ist die entsprechende Navigationseigenschaft.The CourseID property is a foreign key, and the corresponding navigation property is Course. Die Enrollment-Entität wird einer Course-Entität zugeordnet.An Enrollment entity is associated with one Course entity.

Entity Framework Core interpretiert Eigenschaften als Fremdschlüssel, wenn diese den Namen <navigation property name><primary key property name> haben.EF Core interprets a property as a foreign key if it's named <navigation property name><primary key property name>. Beispielsweise StudentID der Fremdschlüssel für die Student-Navigationseigenschaft, da ID der Primärschlüssel der Student-Entität ist.For example,StudentID is the foreign key for the Student navigation property, since the Student entity's primary key is ID. Fremdschlüsseleigenschaften können ebenfalls den Namen <primary key property name> haben.Foreign key properties can also be named <primary key property name>. Beispielsweise CourseID, da CourseID der Primärschlüssel der Course-Entität ist.For example, CourseID since the Course entity's primary key is CourseID.

Die Entität „Course“The Course entity

Entitätsdiagramm „Course“

Erstellen Sie Models/Course.cs mit folgendem Code:Create Models/Course.cs 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; }
    }
}

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft.The Enrollments property is a navigation property. Course-Entitäten können sich auf jede beliebige Anzahl von Enrollment-Entitäten beziehen.A Course entity can be related to any number of Enrollment entities.

Das DatabaseGenerated-Attribut lässt es zu, dass die App den Primärschlüssel angibt, sodass die Datenbank diesen nicht generieren muss.The DatabaseGenerated attribute allows the app to specify the primary key rather than having the database generate it.

Erstellen Sie das Projekt, um sich zu vergewissern, dass keine Compilerfehler vorhanden sind.Build the project to validate that there are no compiler errors.

Gerüstbau der Student-SeitenScaffold Student pages

In diesem Abschnitt verwenden Sie das ASP.Net Core-Gerüstbautool, um Folgendes zu generieren:In this section, you use the ASP.NET Core scaffolding tool to generate:

  • Eine EF Core DbContext-Klasse.An EF Core DbContext class. „context“ ist die Hauptklasse, die die Entity Framework-Funktionen für ein angegebenes Datenmodell koordiniert.The context is the main class that coordinates Entity Framework functionality for a given data model. Diese Klasse wird von der Microsoft.EntityFrameworkCore.DbContext-Klasse abgeleitet.It derives from the Microsoft.EntityFrameworkCore.DbContext class.
  • Razor Pages-Instanzen, die CRUD-Vorgänge (Create, Read, Update, Delete) für die Student-Entität verarbeiten.Razor pages that handle Create, Read, Update, and Delete (CRUD) operations for the Student entity.
  • Erstellen Sie einen Ordner Pages/Students.Create a Pages/Students folder.
  • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Pages/Students, und wählen Sie Hinzufügen > Neues Gerüstelement aus.In Solution Explorer, right-click the Pages/Students folder and select Add > New Scaffolded Item.
  • Im Dialogfeld Add New Scaffold Item (Neues Gerüstelement hinzufügen):In the Add New Scaffold Item dialog:
    • Wählen Sie auf der linken Registerkarte Installiert > Häufig > Razor-Seiten aus.In the left tab, select Installed > Common > Razor Pages
    • Wählen Sie Razor-Seiten mithilfe des Entity Frameworks (CRUD) > Hinzufügen aus.Select Razor Pages using Entity Framework (CRUD) > ADD.
  • Gehen Sie im Dialogfeld Razor Pages mit Entity Framework (CRUD) hinzufügen folgendermaßen vor:In the Add Razor Pages using Entity Framework (CRUD) dialog:
    • Wählen Sie im Dropdownmenü Modellklasse Student (ContosoUniversity.Models) aus.In the Model class drop-down, select Student (ContosoUniversity.Models).
    • Wählen Sie in der Zeile Datenkontextklasse das + -Zeichen (Pluszeichen) aus.In the Data context class row, select the + (plus) sign.
      • Ändern Sie den Datenkontextnamen so, dass er auf SchoolContext anstatt auf ContosoUniversityContext endet.Change the data context name to end in SchoolContext rather than ContosoUniversityContext. Der aktualisierte Kontextname lautet ContosoUniversity.Data.SchoolContext.The updated context name: ContosoUniversity.Data.SchoolContext
    • Wählen Sie Hinzufügen aus.Select Add.

Die folgenden Pakete werden automatisch installiert:The following packages are automatically installed:

  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.VisualStudio.Web.CodeGeneration.Design

Wenn der vorherige Schritt zu einem Fehler führt, erstellen Sie das Projekt, und wiederholen Sie den Gerüstbauschritt.If the preceding step fails, build the project and retry the scaffold step.

Der Gerüstbauprozess:The scaffolding process:

  • Erstellt Razor Pages im Ordner Pages/Students:Creates Razor pages in the Pages/Students folder:
    • Create.cshtml und Create.cshtml.csCreate.cshtml and Create.cshtml.cs
    • Create.cshtml und Delete.cshtml.csDelete.cshtml and Delete.cshtml.cs
    • Details.cshtml und Details.cshtml.csDetails.cshtml and Details.cshtml.cs
    • Edit.cshtml und Edit.cshtml.csEdit.cshtml and Edit.cshtml.cs
    • Index.cshtml und Index.cshtml.csIndex.cshtml and Index.cshtml.cs
  • Erstellt Data/SchoolContext.cs.Creates Data/SchoolContext.cs.
  • Fügt der Abhängigkeitsinjektion in Startup.cs den Kontext hinzu.Adds the context to dependency injection in Startup.cs.
  • legt eine Datenbankverbindungszeichenfolge für appsettings.json festAdds a database connection string to appsettings.json.

DatenbankverbindungszeichenfolgeDatabase connection string

Das Gerüstbautool generiert eine Verbindungszeichenfolge in der Datei appsettings.json .The scaffolding tool generates a connection string in the appsettings.json file.

Die Verbindungszeichenfolge gibt SQL Server LocalDB an:The connection string specifies SQL Server LocalDB:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "SchoolContext": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversityContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

LocalDB ist eine Basisversion der SQL Server Express-Datenbank-Engine, die zwar für die Anwendungsentwicklung, aber nicht für den Produktionseinsatz bestimmt ist.LocalDB is a lightweight version of the SQL Server Express Database Engine and is intended for app development, not production use. Standardmäßig erstellt LocalDB MDF-Dateien im Verzeichnis C:/Users/<user>.By default, LocalDB creates .mdf files in the C:/Users/<user> directory.

Aktualisieren der DatenbankkontextklasseUpdate the database context class

Bei der Datenbankkontextklasse handelt es sich um die Hauptklasse, die die Entity Framework Core-Funktionen für ein angegebenes Datenmodell koordiniert.The main class that coordinates EF Core functionality for a given data model is the database context class. Der Kontext wird aus Microsoft.EntityFrameworkCore.DbContext abgeleitet.The context is derived from Microsoft.EntityFrameworkCore.DbContext. Der Kontext gibt an, welche Entitäten im Datenmodell enthalten sind.The context specifies which entities are included in the data model. In diesem Projekt heißt die Klasse SchoolContext.In this project, the class is named SchoolContext.

Aktualisieren Sie Data/SchoolContext.cs mit folgendem Code:Update Data/SchoolContext.cs with the following code:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

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

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

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

Der obige Code ändert den Singular DbSet<Student> Student in den Plural DbSet<Student> Students.The preceding code changes from the singular DbSet<Student> Student to the plural DbSet<Student> Students. Nehmen Sie eine globale Änderung vor, damit der Code der Razor-Seite mit dem neuen Namen DBSet übereinstimmt: _context.Student.To make the Razor Pages code match the new DBSet name, make a global change from: _context.Student. in _context.Students.to: _context.Students.

Es gibt 8 Vorkommen.There are 8 occurrences.

Da eine Entitätenmenge mehrere Entitäten enthält, bevorzugen viele Entwickler den Plural für DBSet-Eigenschaftennamen.Because an entity set contains multiple entities, many developers prefer the DBSet property names should be plural.

Der hervorgehobene Code:The highlighted code:

  • Erstellt eine DbSet<TEntity>-Eigenschaft für jede Entitätenmenge.Creates a DbSet<TEntity> property for each entity set. Das heißt für Entity Framework Core:In EF Core terminology:
    • Entitätenmengen entsprechen in der Regel einer Datenbanktabelle.An entity set typically corresponds to a database table.
    • Entitäten entsprechen Zeilen in Tabellen.An entity corresponds to a row in the table.
  • Ruft OnModelCreating.Calls OnModelCreating. OnModelCreating:OnModelCreating:
    • Wird aufgerufen, wenn SchoolContext initialisiert wurde, bevor jedoch das Modell gesperrt und zum Initialisieren des Kontexts verwendet wurde.Is called when SchoolContext has been initialized, but before the model has been locked down and used to initialize the context.
    • Ist erforderlich, da die Student-Entität später im Tutorial Verweise auf die anderen Entitäten enthält.Is required because later in the tutorial The Student entity will have references to the other entities.

Erstellen Sie das Projekt, um sich zu vergewissern, dass keine Compilerfehler vorhanden sind.Build the project to verify there are no compiler errors.

Startup.csStartup.cs

ASP.NET Core wird mit Dependency Injection erstellt.ASP.NET Core is built with dependency injection. Dienste (z. B. SchoolContext) werden per Abhängigkeitsinjektion während des App-Starts registriert.Services such as the SchoolContext are registered with dependency injection during app startup. Komponenten, die diese Dienste erfordern (z. B. Razor-Seiten), werden diese Dienste über Konstruktorparameter bereitgestellt.Components that require these services, such as Razor Pages, are provided these services via constructor parameters. Der Konstruktorcode, der eine Datenbankkontextinstanz abruft, wird später in diesem Tutorial erläutert.The constructor code that gets a database context instance is shown later in the tutorial.

Das Gerüstbautool hat die context-Klasse automatisch beim Dependency Injection-Container registriert.The scaffolding tool automatically registered the context class with the dependency injection container.

Die folgenden hervorgehobenen Zeilen wurden beim Gerüstbau hinzugefügt:The following highlighted lines were added by the scaffolder:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

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

Der Name der Verbindungszeichenfolge wird an den Kontext übergeben, indem Sie eine Methode auf einem DbContextOptions-Objekt aufrufen.The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. Für die lokale Entwicklung liest das ASP.NET Core-Konfigurationssystem die Verbindungszeichenfolge aus der Datei appsettings.json .For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Hinzufügen des Filters für die DatenbankausnahmeAdd the database exception filter

Fügen Sie AddDatabaseDeveloperPageExceptionFilter in ConfigureServices hinzu, wie im folgenden Code dargestellt:Add AddDatabaseDeveloperPageExceptionFilter to ConfigureServices as shown in the following code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

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

    services.AddDatabaseDeveloperPageExceptionFilter();
}

Fügen Sie das NuGet-Paket Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore hinzu.Add the Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet package.

Geben Sie Folgendes in die Konsole des Paket-Managers ein, um das NuGet-Paket hinzuzufügen:In the PMC, enter the following to add the NuGet package:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore -Version 5.0.0-rc.2.20475.17

Das NuGet-Paket Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore stellt ASP.NET Core-Middleware für Entity Framework Core-Fehlerseiten bereit.The Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet package provides ASP.NET Core middleware for Entity Framework Core error pages. Diese Middleware hilft bei der Erkennung und Diagnose von Fehlern bei Entity Framework Core-Migrationen.This middleware helps to detect and diagnose errors with Entity Framework Core migrations.

AddDatabaseDeveloperPageExceptionFilter bietet hilfreiche Fehlerinformationen in der Entwicklungsumgebung.The AddDatabaseDeveloperPageExceptionFilter provides helpful error information in the development environment.

Erstellen der DatenbankCreate the database

Aktualisieren Sie Program.cs, um die Datenbank zu erstellen, wenn diese nicht vorhanden ist:Update Program.cs to create the database if it doesn't exist:

using ContosoUniversity.Data;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            CreateDbIfNotExists(host);

            host.Run();
        }

        private static void CreateDbIfNotExists(IHost host)
        {
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var context = services.GetRequiredService<SchoolContext>();
                    context.Database.EnsureCreated();
                    // DbInitializer.Initialize(context);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred creating the DB.");
                }
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Die EnsureCreated-Methode führt keine Aktion aus, wenn eine Datenbank für den Kontext vorhanden ist.The EnsureCreated method takes no action if a database for the context exists. Wenn keine Datenbank vorhanden ist, werden die Datenbank und das Schema erstellt.If no database exists, it creates the database and schema. EnsureCreated aktiviert den folgenden Workflow für die Verarbeitung von Datenmodelländerungen:EnsureCreated enables the following workflow for handling data model changes:

  • Löschen der Datenbank.Delete the database. Alle vorhandenen Daten gehen verloren.Any existing data is lost.
  • Ändern des Datenmodells.Change the data model. Beispielsweise Hinzufügen eines EmailAddress-Felds.For example, add an EmailAddress field.
  • Führen Sie die App aus.Run the app.
  • EnsureCreated erstellt eine Datenbank mit dem neuen Schema.EnsureCreated creates a database with the new schema.

Dieser Workflow funktioniert früh in der Entwicklungsphase gut, wenn sich das Schema rasch weiterentwickelt, solange Sie keine Daten beibehalten müssen.This workflow works well early in development when the schema is rapidly evolving, as long as you don't need to preserve data. Anders verhält es sich, wenn es darum geht, Daten, die in die Datenbank eingegeben wurden, beizubehalten.The situation is different when data that has been entered into the database needs to be preserved. Wenn dies der Fall ist, verwenden Sie Migrationen.When that is the case, use migrations.

Später in der Tutorialserie löschen Sie die Datenbank, die von EnsureCreated erstellt wurde, und verwenden stattdessen Migrationen.Later in the tutorial series, you delete the database that was created by EnsureCreated and use migrations instead. Eine Datenbank, die von EnsureCreated erstellt wird, kann nicht mithilfe von Migrationen aktualisiert werden.A database that is created by EnsureCreated can't be updated by using migrations.

Testen der AppTest the app

  • Führen Sie die App aus.Run the app.
  • Klicken Sie auf den Link Students (Studenten) und anschließend auf Neu erstellen.Select the Students link and then Create New.
  • Testen Sie die Links „Edit“ (Bearbeiten), „Details“ und „Delete“ (Löschen).Test the Edit, Details, and Delete links.

Ausführen eines Seedings für die DatenbankSeed the database

Die EnsureCreated-Methode erstellt eine leere Datenbank.The EnsureCreated method creates an empty database. In diesem Abschnitt wird Code hinzugefügt, der die Datenbank mit Testdaten auffüllt.This section adds code that populates the database with test data.

Erstellen Sie Data/DbInitializer.cs mit dem folgenden Code:Create Data/DbInitializer.cs with the following code:

using ContosoUniversity.Data;
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("2019-09-01")},
                new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")},
                new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")}
            };

            context.Students.AddRange(students);
            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}
            };

            context.Courses.AddRange(courses);
            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},
            };

            context.Enrollments.AddRange(enrollments);
            context.SaveChanges();
        }
    }
}

Der Code überprüft, ob Studenten in der Datenbank vorhanden sind.The code checks if there are any students in the database. Wenn keine Studenten vorhanden sind, werden der Datenbank Testdaten hinzugefügt.If there are no students, it adds test data to the database. Testdaten werden in Arrays anstelle von List<T>-Sammlungen erstellt, um die Leistung zu optimieren.It creates the test data in arrays rather than List<T> collections to optimize performance.

Ersetzen Sie in Program.cs den EnsureCreated-Aufruf durch einen DbInitializer.Initialize-Aufruf:In Program.cs, replace the EnsureCreated call with a DbInitializer.Initialize call:

// context.Database.EnsureCreated();
DbInitializer.Initialize(context);

Beenden Sie die App, falls sie gerade ausgeführt wird, und führen Sie den folgenden Befehl in der Paket-Manager-Konsole (Package Manager Console, PMC) aus:Stop the app if it's running, and run the following command in the Package Manager Console (PMC):

Drop-Database -Confirm

Antworten Sie mit Y, um die Datenbank zu löschen.Respond with Y to delete the database.

  • Starten Sie die App neu.Restart the app.
  • Wählen Sie die Seite „Students“ aus, um die Daten anzuzeigen, mit denen das Seeding ausgeführt wurde.Select the Students page to see the seeded data.

Zeigen Sie die Datenbank anView the database

  • Öffnen Sie über das Menü Ansicht im Visual Studio SQL Server-Objekt-Explorer (SSOX).Open SQL Server Object Explorer (SSOX) from the View menu in Visual Studio.
  • Wählen Sie in SSOX (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID} aus.In SSOX, select (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}. Der Datenbankname wird anhand des Kontextnamens, den Sie zuvor angegeben haben, plus Bindestrich und GUID generiert.The database name is generated from the context name you provided earlier plus a dash and a GUID.
  • Erweitern Sie den Knoten Tabellen.Expand the Tables node.
  • Klicken Sie mit der rechten Maustaste auf die Tabelle Student, und klicken Sie auf Daten anzeigen, um die erstellten Spalten und die in die Tabelle eingefügten Zeilen aufzurufen.Right-click the Student table and click View Data to see the columns created and the rows inserted into the table.
  • Klicken Sie mit der rechten Maustaste auf die Tabelle Student, und klicken Sie auf Code anzeigen, um die Zuordnung des Student-Modells zum Student-Tabellenschema anzuzeigen.Right-click the Student table and click View Code to see how the Student model maps to the Student table schema.

Asynchroner CodeAsynchronous code

Die asynchrone Programmierung ist der Standardmodus für ASP.NET Core und EF Core.Asynchronous programming is the default mode for ASP.NET Core and EF Core.

Der Webserver verfügt nur über eine begrenzte Anzahl von Threads. Daher werden bei hoher Auslastung möglicherweise alle verfügbaren Threads gleichzeitig verwendet.A web server has a limited number of threads available, and in high load situations all of the available threads might be in use. Wenn dies der Fall ist, kann der Server keine neuen Anforderungen verarbeiten, bis die Threads wieder freigegeben werden.When that happens, the server can't process new requests until the threads are freed up. Wenn synchroner Code verwendet wird, kann es sein, dass zwar viele Threads belegt sind, diese aber keine Vorgänge ausführen, da sie auf den Abschluss der E/A-Vorgänge warten.With synchronous code, many threads may be tied up while they aren't doing work because they're waiting for I/O to complete. Wenn asynchroner Code verwendet wird, werden Threads für den Server freigegeben, wenn diese nur auf den Abschluss der E/A-Vorgänge warten, damit andere Anforderungen verarbeitet werden können.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. Das bedeutet, dass es durch asynchronen Code ermöglicht wird, Serverressourcen effizienter zu nutzen, und der Server kann ohne Verzögerungen eine größere Menge von Datenverkehr verarbeiten.As a result, asynchronous code enables server resources to be used more efficiently, and the server can handle more traffic without delays.

Zur Laufzeit bedeutet die Verwendung von asynchronem Code allerdings, dass ein wenig mehr Aufwand entsteht.Asynchronous code does introduce a small amount of overhead at run time. Für Situationen mit wenig Datenverkehr haben diese Leistungseinbußen keine negativen Folgen. Wenn es jedoch eine große Menge an Datenverkehr gibt, ist eine potentielle Verbesserung der Leistung von Bedeutung.For low traffic situations, the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.

Im folgenden Code führen das async-Schlüsselwort, der Task<T>-Rückgabewert, das await-Schlüsselwort und die ToListAsync-Methode dazu, dass der Code asynchron ausgeführt wird.In the following code, the async keyword, Task<T> return value, await keyword, and ToListAsync method make the code execute asynchronously.

public async Task OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
}
  • Das async-Schlüsselwort gibt dem Compiler folgende Anweisungen:The async keyword tells the compiler to:
    • Er soll Rückrufe für Teile des Methodentexts generieren.Generate callbacks for parts of the method body.
    • Er soll das Task-Objekt erstellen, das zurückgegeben wird.Create the Task object that's returned.
  • Der Rückgabetyp Task<T> stellt die derzeit ausgeführten Aufgaben dar.The Task<T> return type represents ongoing work.
  • Das await-Schlüsselwort hat zur Folge, dass der Compiler die Methode in zwei Teile unterteilt.The await keyword causes the compiler to split the method into two parts. Der erste Teil endet mit dem Vorgang, der auf asynchrone Weise gestartet wird.The first part ends with the operation that's started asynchronously. Der zweite Teil wird in eine Rückrufmethode übertragen, die aufgerufen wird, wenn der Vorgang abgeschlossen wird.The second part is put into a callback method that's called when the operation completes.
  • Bei ToListAsync handelt es sich um die asynchrone Version der ToList-Erweiterungsmethode.ToListAsync is the asynchronous version of the ToList extension method.

Behalten Sie Folgendes im Hinterkopf, wenn Sie asynchronen Code schreiben, der Entity Framework Core verwendet:Some things to be aware of when writing asynchronous code that uses EF Core:

  • Es werden nur Anweisungen auf asynchrone Weise ausgeführt, die Abfragen oder Befehle auslösen, die an die Datenbank gesendet werden sollen.Only statements that cause queries or commands to be sent to the database are executed asynchronously. Dazu gehören ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync und SaveChangesAsync.That includes ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync, and SaveChangesAsync. Anweisungen wie var students = context.Students.Where(s => s.LastName == "Davolio"), die nur eine IQueryable-Instanz ändern, sind davon ausgeschlossen.It doesn't include statements that just change an IQueryable, such as var students = context.Students.Where(s => s.LastName == "Davolio").
  • Entity Framework Core-Kontexte sind nicht threadsicher. Versuchen Sie daher nicht, mehrere Vorgänge gleichzeitig auszuführen.An EF Core context isn't thread safe: don't try to do multiple operations in parallel.
  • Wenn Sie von den Leistungsvorteilen durch asynchronen Code profitieren möchten, überprüfen Sie, ob Bibliothekspakete (z.B. zum Paging) asynchronen Code verwenden, wenn sie Entity Framework Core-Methoden aufrufen, die Abfragen an die Datenbank senden.To take advantage of the performance benefits of async code, verify that library packages (such as for paging) use async if they call EF Core methods that send queries to the database.

Weitere Informationen zur asynchronen Programmierung in .NET finden Sie unter Async (Übersicht) und Asynchrone Programmierung mit Async und Await (C#).For more information about asynchronous programming in .NET, see Async Overview and Asynchronous programming with async and await.

Überlegungen zur LeistungPerformance considerations

Im Allgemeinen sollte eine Webseite keine beliebige Anzahl von Zeilen laden.In general, a web page shouldn't be loading an arbitrary number of rows. Eine Abfrage sollte Paging oder ein Verfahren zum Einschränken verwenden.A query should use paging or a limiting approach. Die vorherige Abfrage könnte z. B. Take verwenden, um die Anzahl zurückgegebener Zeilen einzuschränken:For example, the preceding query could use Take to limit the rows returned:

public class IndexModel : PageModel
{
    private readonly SchoolContext _context;
    private readonly MvcOptions _mvcOptions;

    public IndexModel(SchoolContext context, IOptions<MvcOptions> mvcOptions)
    {
        _context = context;
        _mvcOptions = mvcOptions.Value;
    }

    public IList<Student> Student { get;set; }

    public async Task OnGetAsync()
    {
        Student = await _context.Students.Take(
            _mvcOptions.MaxModelBindingCollectionSize).ToListAsync();
    }
}

Durch das Auflisten einer großen Tabelle in einer Sicht kann eine teilweise konstruierte HTTP 200-Antwort zurückgegeben werden, wenn während des Durchlaufens eine Datenbankausnahme auftritt.Enumerating a large table in a view could return a partially constructed HTTP 200 response if a database exception occurs part way through the enumeration.

Der Standardwert von MaxModelBindingCollectionSize ist 1.024.MaxModelBindingCollectionSize defaults to 1024. Der folgende Code legt MaxModelBindingCollectionSize fest.The following code sets MaxModelBindingCollectionSize:

public void ConfigureServices(IServiceCollection services)
{
    int MyMaxModelBindingCollectionSize = 100;
    Int32.TryParse(Configuration["MyMaxModelBindingCollectionSize"],
                               out MyMaxModelBindingCollectionSize);
    
    services.Configure<MvcOptions>(options => 
           options.MaxModelBindingCollectionSize = MyMaxModelBindingCollectionSize);

    services.AddRazorPages();

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

    services.AddDatabaseDeveloperPageExceptionFilter();
}

Das Paging wird später im Tutorial beschrieben.Paging is covered later in the tutorial.

Nächste SchritteNext steps

Dies ist das erste einer Reihe von Tutorials, die zeigen, wie Entity Framework (EF) Core für eine Razor Pages-App mit ASP.NET Core verwendet wird.This is the first in a series of tutorials that show how to use Entity Framework (EF) Core in an ASP.NET Core Razor Pages app. In den Tutorials wird eine Website für eine fiktive Contoso University erstellt.The tutorials build a web site for a fictional Contoso University. Sie enthält Funktionen wie die Zulassung von Studenten, die Erstellung von Kursen und Aufgaben von Dozenten.The site includes functionality such as student admission, course creation, and instructor assignments. In diesem Tutorial wird der Code-First-Ansatz verwendet.The tutorial uses the code first approach. Informationen zum Durcharbeiten dieses Tutorials mit dem Database-First-Ansatz finden Sie in diesem GitHub-Issue.For information on following this tutorial using the database first approach, see this Github issue.

Download or view the completed app (Herunterladen oder anzeigen der vollständigen App).Download or view the completed app. Anweisungen zum Download.Download instructions.

VoraussetzungenPrerequisites

Datenbank-EnginesDatabase engines

Die Visual Studio-Anweisungen verwenden SQL Server LocalDB, eine Version von SQL Server Express, die nur unter Windows ausgeführt werden kann.The Visual Studio instructions use SQL Server LocalDB, a version of SQL Server Express that runs only on Windows.

In den Visual Studio Code-Anweisungen wird SQLite verwendet, eine plattformübergreifende Datenbank-Engine.The Visual Studio Code instructions use SQLite, a cross-platform database engine.

Wenn Sie SQLite verwenden möchten, laden Sie ein Drittanbietertool zum Verwalten und Anzeigen einer SQLite-Datenbank (z.B. DB Browser für SQLite) herunter, und installieren Sie es.If you choose to use SQLite, download and install a third-party tool for managing and viewing a SQLite database, such as DB Browser for SQLite.

ProblembehandlungTroubleshooting

Wenn Sie auf ein Problem stoßen, das Sie nicht lösen können, vergleichen Sie Ihren den Code mit dem vollständigen Projekt.If you run into a problem you can't resolve, compare your code to the completed project. Eine gute Möglichkeit, Hilfe zu erhalten, besteht darin, eine Frage auf StackOverflow.com zu stellen und dabei das ASP.NET Core-Tag oder das EF Core-Tag zu verwenden.A good way to get help is by posting a question to StackOverflow.com, using the ASP.NET Core tag or the EF Core tag.

Die Beispiel-AppThe sample app

Bei der App, die mithilfe dieser Tutorials erstellt werden soll, handelt es sich um eine einfache Website einer Universität.The app built in these tutorials is a basic university web site. Benutzer können Informationen zu den Studenten, Kursen und Dozenten abrufen.Users can view and update student, course, and instructor information. Im Folgenden sind einige Anzeigen dargestellt, die mithilfe dieses Tutorials erstellt werden.Here are a few of the screens created in the tutorial.

Indexseite „Studenten“

Bearbeitungsseite für Studenten

Der Benutzeroberflächenstil dieser Website basiert auf den integrierten Projektvorlagen.The UI style of this site is based on the built-in project templates. Das Tutorial konzentriert sich auf die Verwendung von EF Core und nicht auf die Anpassung der Benutzeroberfläche.The tutorial's focus is on how to use EF Core, not how to customize the UI.

Folgen Sie dem Link am oberen Rand der Seite, um den Quellcode für das vollständige Projekt abzurufen.Follow the link at the top of the page to get the source code for the completed project. Der Ordner cu30 enthält den Code für die ASP.NET Core 3.0-Version des Tutorials.The cu30 folder has the code for the ASP.NET Core 3.0 version of the tutorial. Dateien, die den Status des Codes für die Tutorials 1 bis 7 widerspiegeln, finden Sie im Ordner cu30snapshots.Files that reflect the state of the code for tutorials 1-7 can be found in the cu30snapshots folder.

So führen Sie die APP nach dem Herunterladen des vollständigen Projekts aus:To run the app after downloading the completed project:

  • Erstellen Sie das Projekt.Build the project.

  • Führen Sie folgenden Befehl in der Paket-Manager-Konsole aus:In Package Manager Console (PMC) run the following command:

    Update-Database
    
  • Führen Sie das Projekt aus, um das Seeding der Datenbank auszuführen.Run the project to seed the database.

Erstellen des Web-App-ProjektsCreate the web app project

  • Klicken Sie in Visual Studio im Menü Datei auf Neu > Projekt.From the Visual Studio File menu, select New > Project.
  • Wählen Sie ASP.NET Core-Webanwendung aus.Select ASP.NET Core Web Application.
  • Geben Sie dem Projekt den Namen ContosoUniversity.Name the project ContosoUniversity. Es ist wichtig, genau diesen Namen unter Beachtung von Groß-/Kleinschreibung zu verwenden, sodass die Namespaces beim Kopieren und Einfügen von Code übereinstimmen.It's important to use this exact name including capitalization, so the namespaces match when code is copied and pasted.
  • Wählen Sie in den Dropdownlisten .NET Core und ASP.NET Core 3.0 und anschließend Webanwendung aus.Select .NET Core and ASP.NET Core 3.0 in the dropdowns, and then select Web Application.

Einrichten des WebsitestilsSet up the site style

Richten Sie die Kopfzeile, die Fußzeile und das Menü der Website durch Aktualisieren von Pages/Shared/_Layout.cshtml ein:Set up the site header, footer, and menu by updating Pages/Shared/_Layout.cshtml:

  • Ändern Sie jedes „ContosoUniversity“ in „Contoso University“.Change each occurrence of "ContosoUniversity" to "Contoso University". Diese Begriffskombination kommt dreimal vor.There are three occurrences.

  • Löschen Sie die Menüeinträge Home (Start) und Privacy (Datenschutz), und fügen Sie Einträge für About (Info), Students (Studenten), Courses (Kurse), Instructors (Dozenten) und Departments (Fachbereiche) hinzu.Delete the Home and Privacy menu entries, and add entries for About, Students, Courses, Instructors, and Departments.

Die Änderungen werden hervorgehoben.The changes are highlighted.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Contoso University</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <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-page="/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-page="/About">About</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">Students</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Courses/Index">Courses</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Instructors/Index">Instructors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Departments/Index">Departments</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <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-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

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

Ersetzen Sie in Pages/Index.cshtml die Inhalte der Datei durch den folgenden Code. Dadurch ersetzen Sie den Text zu ASP.NET Core durch Text zu dieser App:In Pages/Index.cshtml, replace the contents of the file with the following code to replace the text about ASP.NET Core with text about this app:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="row mb-auto">
    <div class="col-md-4">
        <div class="row no-gutters border mb-4">
            <div class="col p-4 mb-4 ">
                <p class="card-text">
                    Contoso University is a sample application that
                    demonstrates how to use Entity Framework Core in an
                    ASP.NET Core Razor Pages web app.
                </p>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="row no-gutters border mb-4">
            <div class="col p-4 d-flex flex-column position-static">
                <p class="card-text mb-auto">
                    You can build the application by following the steps in a series of tutorials.
                </p>
                <p>
                    <a href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro" class="stretched-link">See the tutorial</a>
                </p>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="row no-gutters border mb-4">
            <div class="col p-4 d-flex flex-column">
                <p class="card-text mb-auto">
                    You can download the completed project from GitHub.
                </p>
                <p>
                    <a href="https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-rp/intro/samples" class="stretched-link">See project source code</a>
                </p>
            </div>
        </div>
    </div>
</div>

Führen Sie die App aus, um sicherzustellen, dass die Startseite angezeigt wird.Run the app to verify that the home page appears.

Das DatenmodellThe data model

In den folgenden Abschnitten wird ein Datenmodell erstellt:The following sections create a data model:

Datenmodelldiagramm zur Kursanmeldung für Studenten

Ein Student kann für beliebig viele Kurse angemeldet sein, und für jeden Kurs kann eine beliebige Anzahl von Studenten angemeldet sein.A student can enroll in any number of courses, and a course can have any number of students enrolled in it.

Die Entität „Student“The Student entity

Entitätsdiagramm „Student“

  • Erstellen Sie im Projektordner den Ordner Models.Create a Models folder in the project folder.

  • Erstellen Sie Models/Student.cs mit folgendem Code:Create Models/Student.cs 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; }
        }
    }
    

Die ID-Eigenschaft fungiert als Primärschlüsselspalte der Datenbanktabelle, die diesem Kurs entspricht.The ID property becomes the primary key column of the database table that corresponds to this class. Standardmäßig interpretiert Entity Framework Core eine Eigenschaft mit dem Namen ID oder classnameID als Primärschlüssel.By default, EF Core interprets a property that's named ID or classnameID as the primary key. Der alternative, automatisch erkannte Name für den Primärschlüssel der Klasse Student lautet also StudentID.So the alternative automatically recognized name for the Student class primary key is StudentID. Weitere Informationen finden Sie unter EF Core – Schlüssel.For more information, see EF Core - Keys.

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft.The Enrollments property is a navigation property. Navigationseigenschaften enthalten andere Entitäten, die dieser Entität zugehörig sind.Navigation properties hold other entities that are related to this entity. In diesem Fall enthält die Enrollments-Eigenschaft einer Student-Entität alle Enrollment-Entitäten, die mit diesem Studenten in Zusammenhang stehen.In this case, the Enrollments property of a Student entity holds all of the Enrollment entities that are related to that Student. Wenn es z.B. für eine „Student“-Zeile in der Datenbank zwei zugehörige „Enrollment“-Zeilen gibt, enthält die Navigationseigenschaft Enrollments zwei Enrollment-Entitäten.For example, if a Student row in the database has two related Enrollment rows, the Enrollments navigation property contains those two Enrollment entities.

In der-Datenbank ist eine Enrollment-Zeile mit einer Student-Zeile verknüpft, wenn die StudentID-Spalte den ID-Wert des Studenten enthält.In the database, an Enrollment row is related to a Student row if its StudentID column contains the student's ID value. Angenommen, eine Student-Zeile weist die ID=1 auf.For example, suppose a Student row has ID=1. Zugehörige Enrollment-Zeilen weisen die StudentID = 1 auf.Related Enrollment rows will have StudentID = 1. StudentID ist ein Fremdschlüssel in der Enrollment-Tabelle.StudentID is a foreign key in the Enrollment table.

Die Enrollments-Eigenschaft wird als ICollection<Enrollment> definiert, da es möglicherweise mehrere zugehörige Enrollment-Entitäten gibt.The Enrollments property is defined as ICollection<Enrollment> because there may be multiple related Enrollment entities. Sie können andere Sammlungstypen verwenden, z.B. List<Enrollment> oder HashSet<Enrollment>.You can use other collection types, such as List<Enrollment> or HashSet<Enrollment>. Wenn ICollection<Enrollment> verwendet wird, erstellt Entity Framework Core standardmäßig eine HashSet<Enrollment>-Auflistung.When ICollection<Enrollment> is used, EF Core creates a HashSet<Enrollment> collection by default.

Die Entität „Enrollment“The Enrollment entity

Entitätsdiagramm „Enrollment“

Erstellen Sie Models/Enrollment.cs mit folgendem Code:Create Models/Enrollment.cs 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; }
    }
}

Die EnrollmentID-Eigenschaft ist der Primärschlüssel. Diese Entität verwendet das classnameID-Muster anstelle nur der ID.The EnrollmentID property is the primary key; this entity uses the classnameID pattern instead of ID by itself. Wählen Sie für ein Produktionsdatenmodell ein Muster aus, und verwenden Sie es einheitlich.For a production data model, choose one pattern and use it consistently. In diesem Tutorial werden beide Muster verwendet, um zu veranschaulichen, dass beide funktionieren.This tutorial uses both just to illustrate that both work. Wenn Sie ID ohne classname verwenden, ist es einfacher, einige Arten von Datenmodelländerungen zu implementieren.Using ID without classname makes it easier to implement some kinds of data model changes.

Bei der Grade-Eigenschaft handelt es sich um eine enum.The Grade property is an enum. Das Fragezeichen nach der Grade-Typdeklaration gibt an, dass die Grade-Eigenschaft NULL-Werte zulässt.The question mark after the Grade type declaration indicates that the Grade property is nullable. Eine Grade-Eigenschaft mit dem Wert NULL unterscheidet sich von einer Grade-Eigenschaft mit dem Wert 0 (null): Der Wert NULL bedeutet, dass keine Grade-Eigenschaft bekannt ist oder noch keine zugewiesen wurde.A grade that's null is different from a zero grade—null means a grade isn't known or hasn't been assigned yet.

Bei der StudentID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Student ist die entsprechende Navigationseigenschaft.The StudentID property is a foreign key, and the corresponding navigation property is Student. Die Enrollment-Entität wird einer Student-Entität zugewiesen. Das bedeutet, dass die Eigenschaft genau eine Student-Entität enthält.An Enrollment entity is associated with one Student entity, so the property contains a single Student entity.

Bei der CourseID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Course ist die entsprechende Navigationseigenschaft.The CourseID property is a foreign key, and the corresponding navigation property is Course. Die Enrollment-Entität wird einer Course-Entität zugeordnet.An Enrollment entity is associated with one Course entity.

Entity Framework Core interpretiert Eigenschaften als Fremdschlüssel, wenn diese den Namen <navigation property name><primary key property name> haben.EF Core interprets a property as a foreign key if it's named <navigation property name><primary key property name>. Beispielsweise StudentID der Fremdschlüssel für die Student-Navigationseigenschaft, da ID der Primärschlüssel der Student-Entität ist.For example,StudentID is the foreign key for the Student navigation property, since the Student entity's primary key is ID. Fremdschlüsseleigenschaften können ebenfalls den Namen <primary key property name> haben.Foreign key properties can also be named <primary key property name>. Beispielsweise CourseID, da CourseID der Primärschlüssel der Course-Entität ist.For example, CourseID since the Course entity's primary key is CourseID.

Die Entität „Course“The Course entity

Entitätsdiagramm „Course“

Erstellen Sie Models/Course.cs mit folgendem Code:Create Models/Course.cs 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; }
    }
}

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft.The Enrollments property is a navigation property. Course-Entitäten können sich auf jede beliebige Anzahl von Enrollment-Entitäten beziehen.A Course entity can be related to any number of Enrollment entities.

Das DatabaseGenerated-Attribut lässt es zu, dass die App den Primärschlüssel angibt, sodass die Datenbank diesen nicht generieren muss.The DatabaseGenerated attribute allows the app to specify the primary key rather than having the database generate it.

Erstellen Sie das Projekt, um sich zu vergewissern, dass keine Compilerfehler vorhanden sind.Build the project to validate that there are no compiler errors.

Gerüstbau der Student-SeitenScaffold Student pages

In diesem Abschnitt verwenden Sie das ASP.Net Core-Gerüstbautool, um Folgendes zu generieren:In this section, you use the ASP.NET Core scaffolding tool to generate:

  • Eine EF Core context-Klasse.An EF Core context class. „context“ ist die Hauptklasse, die die Entity Framework-Funktionen für ein angegebenes Datenmodell koordiniert.The context is the main class that coordinates Entity Framework functionality for a given data model. Diese Klasse wird von der Microsoft.EntityFrameworkCore.DbContext-Klasse abgeleitet.It derives from the Microsoft.EntityFrameworkCore.DbContext class.
  • Razor Pages-Instanzen, die CRUD-Vorgänge (Create, Read, Update, Delete) für die Student-Entität verarbeiten.Razor pages that handle Create, Read, Update, and Delete (CRUD) operations for the Student entity.
  • Erstellen Sie einen Ordner Students im Ordner Pages.Create a Students folder in the Pages folder.
  • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Pages/Students, und wählen Sie Hinzufügen > Neues Gerüstelement aus.In Solution Explorer, right-click the Pages/Students folder and select Add > New Scaffolded Item.
  • Wählen Sie im Dialogfeld Gerüst hinzufügen den Eintrag Razor Pages mit Entity Framework (CRUD) > Hinzufügen aus.In the Add Scaffold dialog, select Razor Pages using Entity Framework (CRUD) > ADD.
  • Gehen Sie im Dialogfeld Razor Pages mit Entity Framework (CRUD) hinzufügen folgendermaßen vor:In the Add Razor Pages using Entity Framework (CRUD) dialog:
    • Wählen Sie im Dropdownmenü Modellklasse Student (ContosoUniversity.Models) aus.In the Model class drop-down, select Student (ContosoUniversity.Models).
    • Wählen Sie in der Zeile Datenkontextklasse das + -Zeichen (Pluszeichen) aus.In the Data context class row, select the + (plus) sign.
    • Ändern Sie den Datenkontextnamen aus ContosoUniversity.Models.ContosoUniversityContext in ContosoUniversity.Data.SchoolContext.Change the data context name from ContosoUniversity.Models.ContosoUniversityContext to ContosoUniversity.Data.SchoolContext.
    • Wählen Sie Hinzufügen aus.Select Add.

Die folgenden Pakete werden automatisch installiert:The following packages are automatically installed:

  • Microsoft.VisualStudio.Web.CodeGeneration.Design
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.Extensions.Logging.Debug
  • Microsoft.EntityFrameworkCore.Tools

Wenn Sie ein Problem mit dem vorherigen Schritt haben, erstellen Sie das Projekt, und wiederholen Sie den Gerüstbauschritt.If you have a problem with the preceding step, build the project and retry the scaffold step.

Der Gerüstbauprozess:The scaffolding process:

  • Erstellt Razor Pages im Ordner Pages/Students:Creates Razor pages in the Pages/Students folder:
    • Create.cshtml und Create.cshtml.csCreate.cshtml and Create.cshtml.cs
    • Create.cshtml und Delete.cshtml.csDelete.cshtml and Delete.cshtml.cs
    • Details.cshtml und Details.cshtml.csDetails.cshtml and Details.cshtml.cs
    • Edit.cshtml und Edit.cshtml.csEdit.cshtml and Edit.cshtml.cs
    • Index.cshtml und Index.cshtml.csIndex.cshtml and Index.cshtml.cs
  • Erstellt Data/SchoolContext.cs.Creates Data/SchoolContext.cs.
  • Fügt der Abhängigkeitsinjektion in Startup.cs den Kontext hinzu.Adds the context to dependency injection in Startup.cs.
  • legt eine Datenbankverbindungszeichenfolge für appsettings.json festAdds a database connection string to appsettings.json.

DatenbankverbindungszeichenfolgeDatabase connection string

In der Datei appsettings.json wird die Verbindungszeichenfolge SQL Server LocalDB angegeben.The appsettings.json file specifies the connection string SQL Server LocalDB.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "SchoolContext": "Server=(localdb)\\mssqllocaldb;Database=SchoolContext6;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

LocalDB ist eine Basisversion der SQL Server Express-Datenbank-Engine, die zwar für die Anwendungsentwicklung, aber nicht für den Produktionseinsatz bestimmt ist.LocalDB is a lightweight version of the SQL Server Express Database Engine and is intended for app development, not production use. Standardmäßig erstellt LocalDB MDF-Dateien im Verzeichnis C:/Users/<user>.By default, LocalDB creates .mdf files in the C:/Users/<user> directory.

Aktualisieren der DatenbankkontextklasseUpdate the database context class

Bei der Datenbankkontextklasse handelt es sich um die Hauptklasse, die die Entity Framework Core-Funktionen für ein angegebenes Datenmodell koordiniert.The main class that coordinates EF Core functionality for a given data model is the database context class. Der Kontext wird aus Microsoft.EntityFrameworkCore.DbContext abgeleitet.The context is derived from Microsoft.EntityFrameworkCore.DbContext. Der Kontext gibt an, welche Entitäten im Datenmodell enthalten sind.The context specifies which entities are included in the data model. In diesem Projekt heißt die Klasse SchoolContext.In this project, the class is named SchoolContext.

Aktualisieren Sie Data/SchoolContext.cs mit folgendem Code:Update Data/SchoolContext.cs with the following code:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

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

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

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

Der hervorgehobene Code erstellt eine DbSet<TEntity>-Eigenschaft für jede Entitätenmenge.The highlighted code creates a DbSet<TEntity> property for each entity set. Das heißt für Entity Framework Core:In EF Core terminology:

  • Entitätenmengen entsprechen in der Regel einer Datenbanktabelle.An entity set typically corresponds to a database table.
  • Entitäten entsprechen Zeilen in Tabellen.An entity corresponds to a row in the table.

Da eine Entitätenmenge mehrere Entitäten enthält, sollten die DBSet-Eigenschaften Namen im Plural tragen.Since an entity set contains multiple entities, the DBSet properties should be plural names. Da das Gerüstbautool ein Student-DBSet erstellt hat, ändert dieser Schritt den Namen in den Plural Students.Since the scaffolding tool created aStudent DBSet, this step changes it to plural Students.

Damit der Razor Pages-Code mit dem neuen DBSet-Namen übereinstimmt, ändern Sie _context.Student im gesamten Projekt global in _context.Students.To make the Razor Pages code match the new DBSet name, make a global change across the whole project of _context.Student to _context.Students. Es gibt 8 Vorkommen.There are 8 occurrences.

Erstellen Sie das Projekt, um sich zu vergewissern, dass keine Compilerfehler vorhanden sind.Build the project to verify there are no compiler errors.

Startup.csStartup.cs

ASP.NET Core wird mit Dependency Injection erstellt.ASP.NET Core is built with dependency injection. Dienste wie der EF Core-Datenbankkontext werden über Abhängigkeitsinjektion (Dependency Injection) beim Anwendungsstart registriert.Services (such as the EF Core database context) are registered with dependency injection during application startup. Komponenten, die diese Dienste erfordern (z. B. Razor Pages), werden von diesen Diensten über Konstruktorparameter bereitgestellt.Components that require these services (such as Razor Pages) are provided these services via constructor parameters. Der Konstruktorcode, der eine Datenbankkontextinstanz abruft, wird später in diesem Tutorial erläutert.The constructor code that gets a database context instance is shown later in the tutorial.

Das Gerüstbautool hat die context-Klasse automatisch beim Dependency Injection-Container registriert.The scaffolding tool automatically registered the context class with the dependency injection container.

  • In ConfigureServices wurden die hervorgehobenen Zeilen vom Gerüstbau hinzugefügt:In ConfigureServices, the highlighted lines were added by the scaffolder:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    
        services.AddDbContext<SchoolContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
    }
    

Der Name der Verbindungszeichenfolge wird an den Kontext übergeben, indem Sie eine Methode auf einem DbContextOptions-Objekt aufrufen.The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. Für die lokale Entwicklung liest das ASP.NET Core-Konfigurationssystem die Verbindungszeichenfolge aus der Datei appsettings.json .For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Erstellen der DatenbankCreate the database

Aktualisieren Sie Program.cs, um die Datenbank zu erstellen, wenn diese nicht vorhanden ist:Update Program.cs to create the database if it doesn't exist:

using ContosoUniversity.Data;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            CreateDbIfNotExists(host);

            host.Run();
        }

        private static void CreateDbIfNotExists(IHost host)
        {
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var context = services.GetRequiredService<SchoolContext>();
                    context.Database.EnsureCreated();
                    // DbInitializer.Initialize(context);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred creating the DB.");
                }
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Die EnsureCreated-Methode führt keine Aktion aus, wenn eine Datenbank für den Kontext vorhanden ist.The EnsureCreated method takes no action if a database for the context exists. Wenn keine Datenbank vorhanden ist, werden die Datenbank und das Schema erstellt.If no database exists, it creates the database and schema. EnsureCreated aktiviert den folgenden Workflow für die Verarbeitung von Datenmodelländerungen:EnsureCreated enables the following workflow for handling data model changes:

  • Löschen der Datenbank.Delete the database. Alle vorhandenen Daten gehen verloren.Any existing data is lost.
  • Ändern des Datenmodells.Change the data model. Beispielsweise Hinzufügen eines EmailAddress-Felds.For example, add an EmailAddress field.
  • Führen Sie die App aus.Run the app.
  • EnsureCreated erstellt eine Datenbank mit dem neuen Schema.EnsureCreated creates a database with the new schema.

Dieser Workflow funktioniert früh in der Entwicklungsphase gut, wenn sich das Schema rasch weiterentwickelt, solange Sie keine Daten beibehalten müssen.This workflow works well early in development when the schema is rapidly evolving, as long as you don't need to preserve data. Anders verhält es sich, wenn es darum geht, Daten, die in die Datenbank eingegeben wurden, beizubehalten.The situation is different when data that has been entered into the database needs to be preserved. Wenn dies der Fall ist, verwenden Sie Migrationen.When that is the case, use migrations.

Später in der Tutorialserie löschen Sie die Datenbank, die von EnsureCreated erstellt wurde, und verwenden stattdessen Migrationen.Later in the tutorial series, you delete the database that was created by EnsureCreated and use migrations instead. Eine Datenbank, die von EnsureCreated erstellt wird, kann nicht mithilfe von Migrationen aktualisiert werden.A database that is created by EnsureCreated can't be updated by using migrations.

Testen der AppTest the app

  • Führen Sie die App aus.Run the app.
  • Klicken Sie auf den Link Students (Studenten) und anschließend auf Neu erstellen.Select the Students link and then Create New.
  • Testen Sie die Links „Edit“ (Bearbeiten), „Details“ und „Delete“ (Löschen).Test the Edit, Details, and Delete links.

Ausführen eines Seedings für die DatenbankSeed the database

Die EnsureCreated-Methode erstellt eine leere Datenbank.The EnsureCreated method creates an empty database. In diesem Abschnitt wird Code hinzugefügt, der die Datenbank mit Testdaten auffüllt.This section adds code that populates the database with test data.

Erstellen Sie Data/DbInitializer.cs mit dem folgenden Code:Create Data/DbInitializer.cs with the following code:

using ContosoUniversity.Data;
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("2019-09-01")},
                new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")},
                new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")}
            };

            context.Students.AddRange(students);
            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}
            };

            context.Courses.AddRange(courses);
            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},
            };

            context.Enrollments.AddRange(enrollments);
            context.SaveChanges();
        }
    }
}

Der Code überprüft, ob Studenten in der Datenbank vorhanden sind.The code checks if there are any students in the database. Wenn keine Studenten vorhanden sind, werden der Datenbank Testdaten hinzugefügt.If there are no students, it adds test data to the database. Testdaten werden in Arrays anstelle von List<T>-Sammlungen erstellt, um die Leistung zu optimieren.It creates the test data in arrays rather than List<T> collections to optimize performance.

  • Ersetzen Sie in Program.cs den EnsureCreated-Aufruf durch einen DbInitializer.Initialize-Aufruf:In Program.cs, replace the EnsureCreated call with a DbInitializer.Initialize call:

    // context.Database.EnsureCreated();
    DbInitializer.Initialize(context);
    

Beenden Sie die App, falls sie gerade ausgeführt wird, und führen Sie den folgenden Befehl in der Paket-Manager-Konsole (Package Manager Console, PMC) aus:Stop the app if it's running, and run the following command in the Package Manager Console (PMC):

Drop-Database
  • Starten Sie die App neu.Restart the app.

  • Wählen Sie die Seite „Students“ aus, um die Daten anzuzeigen, mit denen das Seeding ausgeführt wurde.Select the Students page to see the seeded data.

Zeigen Sie die Datenbank anView the database

  • Öffnen Sie über das Menü Ansicht im Visual Studio SQL Server-Objekt-Explorer (SSOX).Open SQL Server Object Explorer (SSOX) from the View menu in Visual Studio.
  • Wählen Sie in SSOX (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID} aus.In SSOX, select (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}. Der Datenbankname wird anhand des Kontextnamens, den Sie zuvor angegeben haben, plus Bindestrich und GUID generiert.The database name is generated from the context name you provided earlier plus a dash and a GUID.
  • Erweitern Sie den Knoten Tabellen.Expand the Tables node.
  • Klicken Sie mit der rechten Maustaste auf die Tabelle Student, und klicken Sie auf Daten anzeigen, um die erstellten Spalten und die in die Tabelle eingefügten Zeilen aufzurufen.Right-click the Student table and click View Data to see the columns created and the rows inserted into the table.
  • Klicken Sie mit der rechten Maustaste auf die Tabelle Student, und klicken Sie auf Code anzeigen, um die Zuordnung des Student-Modells zum Student-Tabellenschema anzuzeigen.Right-click the Student table and click View Code to see how the Student model maps to the Student table schema.

Asynchroner CodeAsynchronous code

Die asynchrone Programmierung ist der Standardmodus für ASP.NET Core und EF Core.Asynchronous programming is the default mode for ASP.NET Core and EF Core.

Der Webserver verfügt nur über eine begrenzte Anzahl von Threads. Daher werden bei hoher Auslastung möglicherweise alle verfügbaren Threads gleichzeitig verwendet.A web server has a limited number of threads available, and in high load situations all of the available threads might be in use. Wenn dies der Fall ist, kann der Server keine neuen Anforderungen verarbeiten, bis die Threads wieder freigegeben werden.When that happens, the server can't process new requests until the threads are freed up. Wenn synchroner Code verwendet wird, kann es sein, dass zwar viele Threads belegt sind, diese aber keine Vorgänge ausführen, da sie auf den Abschluss der E/A-Vorgänge warten.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. Wenn asynchroner Code verwendet wird, werden Threads für den Server freigegeben, wenn diese nur auf den Abschluss der E/A-Vorgänge warten, damit andere Anforderungen verarbeitet werden können.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. Das bedeutet, dass es durch asynchronen Code ermöglicht wird, Serverressourcen effizienter zu nutzen, und der Server kann ohne Verzögerungen eine größere Menge von Datenverkehr verarbeiten.As a result, asynchronous code enables server resources to be used more efficiently, and the server can handle more traffic without delays.

Zur Laufzeit bedeutet die Verwendung von asynchronem Code allerdings, dass ein wenig mehr Aufwand entsteht.Asynchronous code does introduce a small amount of overhead at run time. Für Situationen mit wenig Datenverkehr haben diese Leistungseinbußen keine negativen Folgen. Wenn es jedoch eine große Menge an Datenverkehr gibt, ist eine potentielle Verbesserung der Leistung von Bedeutung.For low traffic situations, the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.

Im folgenden Code führen das async-Schlüsselwort, der Task<T>-Rückgabewert, das await-Schlüsselwort und die ToListAsync-Methode dazu, dass der Code asynchron ausgeführt wird.In the following code, the async keyword, Task<T> return value, await keyword, and ToListAsync method make the code execute asynchronously.

public async Task OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
}
  • Das async-Schlüsselwort gibt dem Compiler folgende Anweisungen:The async keyword tells the compiler to:
    • Er soll Rückrufe für Teile des Methodentexts generieren.Generate callbacks for parts of the method body.
    • Er soll das Task-Objekt erstellen, das zurückgegeben wird.Create the Task object that's returned.
  • Der Rückgabetyp Task<T> stellt die derzeit ausgeführten Aufgaben dar.The Task<T> return type represents ongoing work.
  • Das await-Schlüsselwort hat zur Folge, dass der Compiler die Methode in zwei Teile unterteilt.The await keyword causes the compiler to split the method into two parts. Der erste Teil endet mit dem Vorgang, der auf asynchrone Weise gestartet wird.The first part ends with the operation that's started asynchronously. Der zweite Teil wird in eine Rückrufmethode übertragen, die aufgerufen wird, wenn der Vorgang abgeschlossen wird.The second part is put into a callback method that's called when the operation completes.
  • Bei ToListAsync handelt es sich um die asynchrone Version der ToList-Erweiterungsmethode.ToListAsync is the asynchronous version of the ToList extension method.

Behalten Sie Folgendes im Hinterkopf, wenn Sie asynchronen Code schreiben, der Entity Framework Core verwendet:Some things to be aware of when writing asynchronous code that uses EF Core:

  • Es werden nur Anweisungen auf asynchrone Weise ausgeführt, die Abfragen oder Befehle auslösen, die an die Datenbank gesendet werden sollen.Only statements that cause queries or commands to be sent to the database are executed asynchronously. Dazu gehören ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync und SaveChangesAsync.That includes ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync, and SaveChangesAsync. Anweisungen wie var students = context.Students.Where(s => s.LastName == "Davolio"), die nur eine IQueryable-Instanz ändern, sind davon ausgeschlossen.It doesn't include statements that just change an IQueryable, such as var students = context.Students.Where(s => s.LastName == "Davolio").
  • Entity Framework Core-Kontexte sind nicht threadsicher. Versuchen Sie daher nicht, mehrere Vorgänge gleichzeitig auszuführen.An EF Core context isn't thread safe: don't try to do multiple operations in parallel.
  • Wenn Sie von den Leistungsvorteilen durch asynchronen Code profitieren möchten, überprüfen Sie, ob Bibliothekspakete (z.B. zum Paging) asynchronen Code verwenden, wenn sie Entity Framework Core-Methoden aufrufen, die Abfragen an die Datenbank senden.To take advantage of the performance benefits of async code, verify that library packages (such as for paging) use async if they call EF Core methods that send queries to the database.

Weitere Informationen zur asynchronen Programmierung in .NET finden Sie unter Async (Übersicht) und Asynchrone Programmierung mit Async und Await (C#).For more information about asynchronous programming in .NET, see Async Overview and Asynchronous programming with async and await.

Nächste SchritteNext steps

Die Beispiel-Web-App der Contoso University veranschaulicht, wie Sie mit Entity Framework Core (EF Core) und ASP.NET Core eine Razor Pages-App erstellen können.The Contoso University sample web app demonstrates how to create an ASP.NET Core Razor Pages app using Entity Framework (EF) Core.

Bei der Beispiel-App handelt es sich um eine Website für die fiktive Contoso University.The sample app is a web site for a fictional Contoso University. Sie enthält Funktionen wie die Zulassung von Studenten, die Erstellung von Kursen und Aufgaben von Dozenten.It includes functionality such as student admission, course creation, and instructor assignments. Dies ist die erste Seite eines mehrseitigen Tutorials, in dem die Erstellung der Beispiel-App der Contoso University erläutert wird.This page is the first in a series of tutorials that explain how to build the Contoso University sample app.

Download or view the completed app (Herunterladen oder anzeigen der vollständigen App).Download or view the completed app. Anweisungen zum Download.Download instructions.

VoraussetzungenPrerequisites

Visual Studio 2019 mit den folgenden Workloads:Visual Studio 2019 with the following workloads:

  • ASP.NET und WebentwicklungASP.NET and web development
  • Plattformübergreifende .NET Core-Entwicklung.NET Core cross-platform development

Kenntnisse zu Razor Pages.Familiarity with Razor Pages. Einsteiger sollten den Artikel Erste Schritte mit Razor Pages lesen, bevor sie mit dieser Tutorialreihe beginnen.New programmers should complete Get started with Razor Pages before starting this series.

ProblembehandlungTroubleshooting

Wenn Sie auf ein Problem stoßen, das Sie nicht lösen können, sollten Sie versuchen, Ihren Code mit dem abgeschlossenen Projekt zu vergleichen.If you run into a problem you can't resolve, you can generally find the solution by comparing your code to the completed project. Sie können auch Hilfe erhalten, indem Sie eine Frage zu ASP.NET Core oder EF Core auf stackoverflow.com stellen.A good way to get help is by posting a question to StackOverflow.com for ASP.NET Core or EF Core.

Die Web-App der Contoso UniversityThe Contoso University web app

Bei der App, die mithilfe dieser Tutorials erstellt werden soll, handelt es sich um eine einfache Website einer Universität.The app built in these tutorials is a basic university web site.

Benutzer können Informationen zu den Studenten, Kursen und Dozenten abrufen.Users can view and update student, course, and instructor information. Im Folgenden sind einige Anzeigen dargestellt, die mithilfe dieses Tutorials erstellt werden.Here are a few of the screens created in the tutorial.

Indexseite „Studenten“

Bearbeitungsseite für Studenten

Der Benutzeroberflächenstil dieser Website ähnelt den durch die integrierten Vorlagen generierten Seiten.The UI style of this site is close to what's generated by the built-in templates. In diesem Tutorial geht es um EF Core mit Razor Pages, nicht um die Benutzeroberfläche.The tutorial focus is on EF Core with Razor Pages, not the UI.

Erstellen der Razor Pages-Web-App „ContosoUniversity“Create the ContosoUniversity Razor Pages web app

  • Klicken Sie in Visual Studio im Menü Datei auf Neu > Projekt.From the Visual Studio File menu, select New > Project.
  • Erstellen Sie eine neue ASP.NET Core-Webanwendung.Create a new ASP.NET Core Web Application. Geben Sie dem Projekt den Namen ContosoUniversity.Name the project ContosoUniversity. Es ist wichtig, dass Sie dem Projekt ContosoUniversity zu nennen, sodass die Namespaces übereinstimmen, wenn der Code kopiert und eingefügt wird.It's important to name the project ContosoUniversity so the namespaces match when code is copy/pasted.
  • Wählen Sie in der Dropdownliste ASP.NET Core 2.1 und anschließend Webanwendung aus.Select ASP.NET Core 2.1 in the dropdown, and then select Web Application.

Bilder zu den vorherigen Schritten finden Sie unter Erstellen einer Razor Pages-Web-App.For images of the preceding steps, see Create a Razor web app. Führen Sie die App aus.Run the app.

Einrichten des WebsitestilsSet up the site style

Sie können das Websitemenü, das Layout und die Startseite über einige Änderungen einrichten.A few changes set up the site menu, layout, and home page. Aktualisieren Sie Pages/Shared/_Layout.cshtml mit folgenden Änderungen:Update Pages/Shared/_Layout.cshtml with the following changes:

  • Ändern Sie jedes „ContosoUniversity“ in „Contoso University“.Change each occurrence of "ContosoUniversity" to "Contoso University". Diese Begriffskombination kommt dreimal vor.There are three occurrences.

  • Fügen Sie Menüeinträge für Studenten, Kurse, Dozenten und Abteilungen hinzu, und löschen Sie den Menüeintrag Kontakt.Add menu entries for Students, Courses, Instructors, and Departments, and delete the Contact menu entry.

Die Änderungen werden hervorgehoben.The changes are highlighted. (Es wird nicht das gesamte Markup angezeigt.)(All the markup is not displayed.)

<!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" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/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" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">Contoso University</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-page="/Index">Home</a></li>
                    <li><a asp-page="/About">About</a></li>
                    <li><a asp-page="/Students/Index">Students</a></li>
                    <li><a asp-page="/Courses/Index">Courses</a></li>
                    <li><a asp-page="/Instructors/Index">Instructors</a></li>
                    <li><a asp-page="/Departments/Index">Departments</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2018 : Contoso University</p>
        </footer>
    </div>

    @*Remaining markup not shown for brevity.*@

Ersetzen Sie in Pages/Index.cshtml die Inhalte der Datei durch den folgenden Code. Dadurch ersetzen Sie den Text zu ASP.NET und MVC durch Text zu dieser App:In Pages/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 app:

@page
@model IndexModel
@{
    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 Razor Pages web app.
        </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.microsoft.com/aspnet/core/data/ef-rp/intro">
                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/dotnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-rp/intro/samples/">
                See project source code &raquo;
            </a>
        </p>
    </div>
</div>

Erstellen des DatenmodellsCreate the data model

Erstellen Sie Entitätsklassen für die Contoso University-App.Create entity classes for the Contoso University app. Beginnen Sie mit dem folgenden drei Entitäten:Start with the following three entities:

Datenmodelldiagramm zur Kursanmeldung für Studenten

Es besteht eine 1:n-Beziehung zwischen der Student- und der Enrollment-Entität.There's a one-to-many relationship between Student and Enrollment entities. Es besteht eine 1:n-Beziehung zwischen der Course- und der Enrollment-Entität.There's a one-to-many relationship between Course and Enrollment entities. Jeder Student kann sich für eine beliebige Anzahl von Kursen anmelden.A student can enroll in any number of courses. Für jeden Kurs kann sich eine beliebige Anzahl von Studenten anmelden.A course can have any number of students enrolled in it.

In den folgenden Abschnitten wird für jede dieser Entitäten eine Klasse erstellt.In the following sections, a class for each one of these entities is created.

Die Entität „Student“The Student entity

Entitätsdiagramm „Student“

Erstellen Sie einen Ordner Models (Modelle).Create a Models folder. Erstellen Sie mit dem folgenden Code im Ordner Models (Modelle) eine Klassendatei mit dem Namen Student.cs:In the Models folder, create a class file named Student.cs 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; }
    }
}

Die ID-Eigenschaft fungiert als Primärschlüsselspalte der Datenbanktabelle, die dieser Klasse entspricht.The ID property becomes the primary key column of the database (DB) table that corresponds to this class. Standardmäßig interpretiert Entity Framework Core eine Eigenschaft mit dem Namen ID oder classnameID als Primärschlüssel.By default, EF Core interprets a property that's named ID or classnameID as the primary key. In classnameID ist classname der Name der Klasse.In classnameID, classname is the name of the class. Der Primärschlüssel, der alternativ automatisch erkannt wurde, ist im vorherigen Beispiel StudentID.The alternative automatically recognized primary key is StudentID in the preceding example.

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft.The Enrollments property is a navigation property. Navigationseigenschaften werden mit anderen Entitäten verknüpft, die dieser Entität zugehörig sind.Navigation properties link to other entities that are related to this entity. In diesem Fall enthält die Enrollments-Eigenschaft einer Student entity all diese Enrollment-Entitäten, die mit diesem Student in Zusammenhang stehen.In this case, the Enrollments property of a Student entity holds all of the Enrollment entities that are related to that Student. Wenn es z.B. für eine „Student“-Zeile in der Datenbank zwei zugehörige „Enrollment“-Zeilen gibt, enthält die Navigationseigenschaft Enrollments zwei Enrollment-Entitäten.For example, if a Student row in the DB has two related Enrollment rows, the Enrollments navigation property contains those two Enrollment entities. Bei einer zugehörigen Enrollment-Zeile handelt es sich um eine Zeile, die den Wert des Primärschlüssels des Studenten in der StudentID-Spalte enthält.A related Enrollment row is a row that contains that student's primary key value in the StudentID column. Nehmen Sie z.B. an, dass es für den Studenten mit ID=1 zwei Zeilen in der Enrollment-Tabelle gibt.For example, suppose the student with ID=1 has two rows in the Enrollment table. Die Enrollment-Tabelle verfügt über zwei Zeilen mit StudentID=1.The Enrollment table has two rows with StudentID = 1. Bei StudentID handelt es sich um einen Fremdschlüssel in der Enrollment-Tabelle, der den Studenten in der Student-Tabelle angibt.StudentID is a foreign key in the Enrollment table that specifies the student in the Student table.

Wenn in einer Navigationseigenschaft mehrere Entitäten gespeichert werden können, muss es sich um einen Listentyp wie ICollection<T> handeln.If a navigation property can hold multiple entities, the navigation property must be a list type, such as ICollection<T>. ICollection<T> oder ein Typ wie List<T> oder HashSet<T> können angegeben werden.ICollection<T> can be specified, or a type such as List<T> or HashSet<T>. Wenn ICollection<T> verwendet wird, erstellt Entity Framework Core standardmäßig eine HashSet<T>-Auflistung.When ICollection<T> is used, EF Core creates a HashSet<T> collection by default. Navigationseigenschaften, die mehrere Entitäten enthalten, entstehen auf der Grundlage von m:n- oder 1:n-Beziehungen.Navigation properties that hold multiple entities come from many-to-many and one-to-many relationships.

Die Entität „Enrollment“The Enrollment entity

Entitätsdiagramm „Enrollment“

Erstellen Sie mit dem folgenden Code im Ordner Models (Modelle) eine Enrollment.cs-Datei:In the Models folder, create Enrollment.cs 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; }
    }
}

Bei der EnrollmentID-Eigenschaft handelt es sich um den Primärschlüssel.The EnrollmentID property is the primary key. Diese Entität verwendet genau wie die Student-Entität das classnameID-Muster anstelle von ID.This entity uses the classnameID pattern instead of ID like the Student entity. In der Regel wählen Entwickler ein Muster aus und verwenden dieses im gesamten Datenmodell.Typically developers choose one pattern and use it throughout the data model. In einem der nächsten Tutorials wird erläutert, wie Sie eine ID ohne Klassennamen verwenden, um die Vererbung einfacher in das Datenmodell zu implementieren.In a later tutorial, using ID without classname is shown to make it easier to implement inheritance in the data model.

Bei der Grade-Eigenschaft handelt es sich um eine enum.The Grade property is an enum. Das Fragezeichen nach der Grade-Typdeklaration gibt an, dass die Grade-Eigenschaft NULL-Werte zulässt.The question mark after the Grade type declaration indicates that the Grade property is nullable. Eine Grade-Eigenschaft mit dem Wert NULL unterscheidet sich von einer Grade-Eigenschaft mit dem Wert 0 (null). Der Wert NULL bedeutet, dass keine Grade-Eigenschaft bekannt ist oder noch keine zugewiesen wurde.A grade that's null is different from a zero grade -- null means a grade isn't known or hasn't been assigned yet.

Bei der StudentID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Student ist die entsprechende Navigationseigenschaft.The StudentID property is a foreign key, and the corresponding navigation property is Student. Die Enrollment-Entität wird einer Student-Entität zugewiesen. Das bedeutet, dass die Eigenschaft genau eine Student-Entität enthält.An Enrollment entity is associated with one Student entity, so the property contains a single Student entity. Die Student-Entität unterscheidet sich von der Student.Enrollments-Navigationseigenschaft, die mehrere Enrollment-Entitäten enthält.The Student entity differs from the Student.Enrollments navigation property, which contains multiple Enrollment entities.

Bei der CourseID-Eigenschaft handelt es sich um einen Fremdschlüssel, und Course ist die entsprechende Navigationseigenschaft.The CourseID property is a foreign key, and the corresponding navigation property is Course. Die Enrollment-Entität wird einer Course-Entität zugeordnet.An Enrollment entity is associated with one Course entity.

Entity Framework Core interpretiert Eigenschaften als Fremdschlüssel, wenn diese den Namen <navigation property name><primary key property name> haben.EF Core interprets a property as a foreign key if it's named <navigation property name><primary key property name>. Beispielsweise StudentID für die Student-Navigationseigenschaft, da ID der Primärschlüssel der Student-Entität ist.For example,StudentID for the Student navigation property, since the Student entity's primary key is ID. Fremdschlüsseleigenschaften können ebenfalls den Namen <primary key property name> haben.Foreign key properties can also be named <primary key property name>. Beispielsweise CourseID, da CourseID der Primärschlüssel der Course-Entität ist.For example, CourseID since the Course entity's primary key is CourseID.

Die Entität „Course“The Course entity

Entitätsdiagramm „Course“

Erstellen Sie mit dem folgenden Code im Ordner Models (Modelle) eine Course.cs-Datei:In the Models folder, create Course.cs 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; }
    }
}

Die Enrollments-Eigenschaft ist eine Navigationseigenschaft.The Enrollments property is a navigation property. Course-Entitäten können sich auf jede beliebige Anzahl von Enrollment-Entitäten beziehen.A Course entity can be related to any number of Enrollment entities.

Das DatabaseGenerated-Attribut lässt es zu, dass die App den Primärschlüssel angibt, sodass die Datenbank diesen nicht generieren muss.The DatabaseGenerated attribute allows the app to specify the primary key rather than having the DB generate it.

Erstellen des Gerüsts für das StudentenmodellScaffold the student model

In diesem Abschnitt wird das Gerüst für das Studentenmodell erstellt.In this section, the student model is scaffolded. Mit dem Tool für den Gerüstbau werden Seiten für die Vorgänge „Create“ (Erstellen), „Read“ (Lesen), „Update“ (Aktualisieren) und „Delete“ (Löschen), kurz CRUD-Vorgänge, für das Studentenmodell erstellt.That is, the scaffolding tool produces pages for Create, Read, Update, and Delete (CRUD) operations for the student model.

  • Erstellen Sie das Projekt.Build the project.
  • Erstellen Sie den Ordner Pages/Students.Create the Pages/Students folder.
  • Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Pages/Students, und wählen Sie Hinzufügen > Neues Gerüstelement aus.In Solution Explorer, right click on the Pages/Students folder > Add > New Scaffolded Item.
  • Wählen Sie im Dialogfeld Gerüst hinzufügen den Eintrag Razor Pages mit Entity Framework (CRUD) > Hinzufügen aus.In the Add Scaffold dialog, select Razor Pages using Entity Framework (CRUD) > ADD.

Vervollständigen Sie das Dialogfeld Add Razor Pages using Entity Framework (CRUD) (Razor-Seiten mithilfe des Entity Frameworks (CRUD) hinzufügen):Complete the Add Razor Pages using Entity Framework (CRUD) dialog:

  • Wählen Sie im Dropdownmenü Modellklasse Student (ContosoUniversity.Models) aus.In the Model class drop-down, select Student (ContosoUniversity.Models).
  • Wählen Sie in der Zeile Datenkontextklasse das Pluszeichen ( + ) aus, und ändern Sie den generierten Namen in ContosoUniversity.Models.SchoolContext.In the Data context class row, select the + (plus) sign and change the generated name to ContosoUniversity.Models.SchoolContext.
  • Wählen Sie im Dropdownmenü Datenkontextklasse ContosoUniversity.Models.SchoolContext aus.In the Data context class drop-down, select ContosoUniversity.Models.SchoolContext
  • Wählen Sie Hinzufügen aus.Select Add.

CRUD-Dialogfeld

Wenn Sie Probleme mit dem vorherigen Schritt haben, finden Sie weitere Informationen unter Erstellen des Gerüsts für das Filmmodell.See Scaffold the movie model if you have a problem with the preceding step.

Der Gerüstprozess hat folgende Dateien erstellt und geändert:The scaffold process created and changed the following files:

Erstellte DateienFiles created

  • Pages/Students/Create.cshtml.cs ( bzw. /Delete, /Details, /Edit, /Index).Pages/Students Create, Delete, Details, Edit, Index.
  • Data/SchoolContext.csData/SchoolContext.cs

DateiupdatesFile updates

  • Startup.cs: Die Änderungen an dieser Datei werden im nächsten Abschnitt ausführlich erläutert.Startup.cs : Changes to this file are detailed in the next section.
  • appsettings.json : Die Verbindungszeichenfolge, die zum Herstellen einer Verbindung mit einer lokalen Datenbank verwendet wird, wurde hinzugefügt.appsettings.json : The connection string used to connect to a local database is added.

Überprüfen des mit Dependency Injection registrierten KontextsExamine the context registered with dependency injection

ASP.NET Core wird mit Dependency Injection erstellt.ASP.NET Core is built with dependency injection. Dienste (z.B. der Datenbankkontext Entity Framework Core) werden über Dependency Injection beim Anwendungsstart registriert.Services (such as the EF Core DB context) are registered with dependency injection during application startup. Komponenten, die diese Dienste erfordern (z. B. Razor Pages), werden von diesen Diensten über Konstruktorparameter bereitgestellt.Components that require these services (such as Razor Pages) are provided these services via constructor parameters. Der Konstruktorcode, der eine Datenbankkontextinstanz abruft, wird später in diesem Tutorial erläutert.The constructor code that gets a db context instance is shown later in the tutorial.

Das Gerüstbautool hat automatisch einen Datenbankkontext erstellt und diesen mit dem Dependency Injection-Container registriert.The scaffolding tool automatically created a DB Context and registered it with the dependency injection container.

Untersuchen Sie die Methode ConfigureServices in Startup.cs.Examine the ConfigureServices method in Startup.cs. Die hervorgehobene Zeile wurde vom Gerüst hinzugefügt:The highlighted line was added by the scaffolder:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for 
        //non -essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

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

Der Name der Verbindungszeichenfolge wird an den Kontext übergeben, indem Sie eine Methode auf einem DbContextOptions-Objekt aufrufen.The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. Für die lokale Entwicklung liest das ASP.NET Core-Konfigurationssystem die Verbindungszeichenfolge aus der Datei appsettings.json .For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Aktualisieren der Main-MethodeUpdate main

Ändern Sie in der Program.cs-Datei die Main-Methode, um die folgenden Vorgänge auszuführen:In Program.cs, modify the Main method to do the following:

  • Rufen Sie eine Datenbankkontextinstanz aus dem Dependency Injection-Container ab.Get a DB context instance from the dependency injection container.
  • Rufen Sie EnsureCreated auf.Call the EnsureCreated.
  • Löschen Sie den Kontext, wenn die EnsureCreated-Methode abgeschlossen ist.Dispose the context when the EnsureCreated method completes.

Der folgende Code zeigt die aktualisierte Program.cs-Datei.The following code shows the updated Program.cs file.

using ContosoUniversity.Models;                   // SchoolContext
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;   // CreateScope
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
    public class Program
    {
        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>();
                    context.Database.EnsureCreated();
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred creating the DB.");
                }
            }

            host.Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

EnsureCreated stellt sicher, dass die Datenbank für den Kontext vorhanden ist.EnsureCreated ensures that the database for the context exists. Wenn sie vorhanden ist, werden keine Aktionen durchgeführt.If it exists, no action is taken. Wenn sie nicht vorhanden ist, werden die Datenbank und alle Schemas erstellt.If it does not exist, then the database and all its schema are created. EnsureCreated verwendet keine Migrationen, um die Datenbank zu erstellen.EnsureCreated does not use migrations to create the database. Eine Datenbank, die mit EnsureCreated erstellt wird, kann später nicht mithilfe von Migrationen aktualisiert werden.A database that is created with EnsureCreated cannot be later updated using migrations.

EnsureCreated wird beim Starten der App aufgerufen, wodurch der folgende Workflow ermöglicht wird:EnsureCreated is called on app start, which allows the following work flow:

  • Löschen Sie die Datenbank.Delete the DB.
  • Ändern Sie das Datenbankschema, also fügen Sie z.B. ein EmailAddress-Feld hinzu.Change the DB schema (for example, add an EmailAddress field).
  • Führen Sie die App aus.Run the app.
  • Über EnsureCreated wird eine Datenbank mit der EmailAddress-Spalte erstellt.EnsureCreated creates a DB with theEmailAddress column.

EnsureCreated eignet sich am Anfang der Entwicklung, wenn das Schema schnell weiterentwickelt wird.EnsureCreated is convenient early in development when the schema is rapidly evolving. Im Verlauf des Tutorials wird die Datenbank gelöscht, und Migrationen werden verwendet.Later in the tutorial the DB is deleted and migrations are used.

Testen der AppTest the app

Führen Sie die App aus, und akzeptieren Sie die cookierichtlinie.Run the app and accept the cookie policy. Diese App bewahrt keine personenbezogenen Informationen auf.This app doesn't keep personal information. Weitere Informationen zur cookierichtlinie finden Sie auf der Seite EU General Data Protection Regulation (GDPR) support (Unterstützung für die Datenschutz-Grundverordnung (DSGVO) der EU).You can read about the cookie policy at EU General Data Protection Regulation (GDPR) support.

  • Klicken Sie auf den Link Students (Studenten) und anschließend auf Neu erstellen.Select the Students link and then Create New.
  • Testen Sie die Links „Edit“ (Bearbeiten), „Details“ und „Delete“ (Löschen).Test the Edit, Details, and Delete links.

Untersuchen des Datenbankkontexts „SchoolContext“Examine the SchoolContext DB context

Bei der Datenbankkontextklasse handelt es sich um die Hauptklasse, die die Entity Framework Core-Funktionen für ein angegebenes Datenmodell koordiniert.The main class that coordinates EF Core functionality for a given data model is the DB context class. Der Datenkontext wird von Microsoft.EntityFrameworkCore.DbContext abgeleitet.The data context is derived from Microsoft.EntityFrameworkCore.DbContext. Der Datenkontext gibt an, welche Entitäten im Datenmodell enthalten sind.The data context specifies which entities are included in the data model. In diesem Projekt heißt die Klasse SchoolContext.In this project, the class is named SchoolContext.

Aktualisieren Sie SchoolContext.cs mit folgendem Code:Update SchoolContext.cs with the following code:

using Microsoft.EntityFrameworkCore;

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

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

Der hervorgehobene Code erstellt eine DbSet<TEntity>-Eigenschaft für jede Entitätenmenge.The highlighted code creates a DbSet<TEntity> property for each entity set. Das heißt für Entity Framework Core:In EF Core terminology:

  • Entitätenmengen entsprechen in der Regel einer Datenbanktabelle.An entity set typically corresponds to a DB table.
  • Entitäten entsprechen Zeilen in Tabellen.An entity corresponds to a row in the table.

DbSet<Enrollment> und DbSet<Course> können ausgelassen werden.DbSet<Enrollment> and DbSet<Course> could be omitted. Diese sind implizit in Entity Framework Core enthalten, da die Student-Entität auf die Enrollment-Entität verweist, und die Enrollment-Entität auf die Course-Entität verweist.EF Core includes them implicitly because the Student entity references the Enrollment entity, and the Enrollment entity references the Course entity. Behalten Sie für dieses Tutorial DbSet<Enrollment> und DbSet<Course> im SchoolContext-Kontext.For this tutorial, keep DbSet<Enrollment> and DbSet<Course> in the SchoolContext.

SQL Server Express LocalDBSQL Server Express LocalDB

Die Verbindungszeichenfolge gibt SQL Server LocalDB an.The connection string specifies SQL Server LocalDB. LocalDB ist eine Basisversion der SQL Server Express-Datenbank-Engine, die zwar für die Anwendungsentwicklung, aber nicht für den Produktionseinsatz bestimmt ist.LocalDB is a lightweight version of the SQL Server Express Database Engine and is intended for app development, not production use. LocalDB wird bedarfsgesteuert gestartet und im Benutzermodus ausgeführt, sodass keine komplexe Konfiguration anfällt.LocalDB starts on demand and runs in user mode, so there's no complex configuration. Standardmäßig erstellt LocalDB .mdf-Datenbankdateien im C:/Users/<user>-Verzeichnis.By default, LocalDB creates .mdf DB files in the C:/Users/<user> directory.

Hinzufügen von Code zum Initialisieren der Datenbank mithilfe von TestdatenAdd code to initialize the DB with test data

Entity Framework Core erstellt eine leere Datenbank.EF Core creates an empty DB. In diesem Abschnitt wird eine Initialize-Methode geschrieben, um diese mit Testdaten aufzufüllen.In this section, an Initialize method is written to populate it with test data.

Erstellen Sie im Ordner Data eine neuen Klassendatei mit dem Namen DbInitializer.cs, und fügen Sie den folgenden Code hinzu:In the Data folder, create a new class file named DbInitializer.cs and add the following code:

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

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

            // Look for any students.
            if (context.Student.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.Student.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.Course.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.Enrollment.Add(e);
            }
            context.SaveChanges();
        }
    }
}

Hinweis: Der vorherige Code verwendet Models für den Namespace (namespace ContosoUniversity.Models) statt Data.Note: The preceding code uses Models for the namespace (namespace ContosoUniversity.Models) rather than Data. Models entspricht dem vom Gerüst generierten Code.Models is consistent with the scaffolder-generated code. Weitere Informationen finden Sie in diesem GitHub-Gerüstbau-Problem.For more information, see this GitHub scaffolding issue.

Der Code überprüft, ob Studenten in der Datenbank enthalten sind.The code checks if there are any students in the DB. Wenn keine Studenten in der Datenbank enthalten sind, wird diese mit Testdaten initialisiert.If there are no students in the DB, the DB is initialized with test data. Testdaten werden in Arrays anstelle von List<T>-Auflistungen geladen, um die Leistung zu optimieren.It loads test data into arrays rather than List<T> collections to optimize performance.

Die EnsureCreated-Methode erstellt automatisch die Datenbank für den Datenbankkontext.The EnsureCreated method automatically creates the DB for the DB context. Wenn die Datenbank vorhanden ist, wird EnsureCreated zurückgegeben, ohne Änderungen an der Datenbank vorzunehmen.If the DB exists, EnsureCreated returns without modifying the DB.

Ändern Sie in Program.cs die Main-Methode, um Initialize aufzurufen:In Program.cs, modify the Main method to call Initialize:

public class Program
{
    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>();
                // using ContosoUniversity.Data; 
                DbInitializer.Initialize(context);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred creating the DB.");
            }
        }

        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Beenden Sie die App, falls sie gerade ausgeführt wird, und führen Sie den folgenden Befehl in der Paket-Manager-Konsole (Package Manager Console, PMC) aus:Stop the app if it's running, and run the following command in the Package Manager Console (PMC):

Drop-Database

Abrufen der DatenbankView the DB

Der Datenbankname wird anhand des Kontextnamens, den Sie zuvor angegeben haben, plus Bindestrich und GUID generiert.The database name is generated from the context name you provided earlier plus a dash and a GUID. Daher lautet der Name der Datenbank „SchoolContext-{GUID}“.Thus, the database name will be "SchoolContext-{GUID}". Die GUID ist für jeden Benutzer unterschiedlich.The GUID will be different for each user. Öffnen Sie über das Menü Ansicht im Visual Studio SQL Server-Objekt-Explorer (SSOX).Open SQL Server Object Explorer (SSOX) from the View menu in Visual Studio. Klicken Sie im SSOX auf (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID} .In SSOX, click (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}.

Erweitern Sie den Knoten Tabellen.Expand the Tables node.

Klicken Sie mit der rechten Maustaste auf die Tabelle Student, und klicken Sie auf Daten anzeigen, um die erstellten Spalten und die in die Tabelle eingefügten Zeilen aufzurufen.Right-click the Student table and click View Data to see the columns created and the rows inserted into the table.

Asynchroner CodeAsynchronous code

Die asynchrone Programmierung ist der Standardmodus für ASP.NET Core und EF Core.Asynchronous programming is the default mode for ASP.NET Core and EF Core.

Der Webserver verfügt nur über eine begrenzte Anzahl von Threads. Daher werden bei hoher Auslastung möglicherweise alle verfügbaren Threads gleichzeitig verwendet.A web server has a limited number of threads available, and in high load situations all of the available threads might be in use. Wenn dies der Fall ist, kann der Server keine neuen Anforderungen verarbeiten, bis die Threads wieder freigegeben werden.When that happens, the server can't process new requests until the threads are freed up. Wenn synchroner Code verwendet wird, kann es sein, dass zwar viele Threads belegt sind, diese aber keine Vorgänge ausführen, da sie auf den Abschluss der E/A-Vorgänge warten.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. Wenn asynchroner Code verwendet wird, werden Threads für den Server freigegeben, wenn diese nur auf den Abschluss der E/A-Vorgänge warten, damit andere Anforderungen verarbeitet werden können.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. Das bedeutet, dass es durch asynchronen Code ermöglicht wird, Serverressourcen effizienter zu nutzen, und der Server kann ohne Verzögerungen eine größere Menge von Datenverkehr verarbeiten.As a result, asynchronous code enables server resources to be used more efficiently, and the server is enabled to handle more traffic without delays.

Zur Laufzeit bedeutet die Verwendung von asynchronem Code allerdings, dass ein wenig mehr Aufwand entsteht.Asynchronous code does introduce a small amount of overhead at run time. Für Situationen mit wenig Datenverkehr haben diese Leistungseinbußen keine negativen Folgen. Wenn es jedoch eine große Menge an Datenverkehr gibt, ist eine potentielle Verbesserung der Leistung von Bedeutung.For low traffic situations, the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.

Im folgenden Code führen das async-Schlüsselwort, der Task<T>-Rückgabewert, das await-Schlüsselwort und die ToListAsync-Methode dazu, dass der Code asynchron ausgeführt wird.In the following code, the async keyword, Task<T> return value, await keyword, and ToListAsync method make the code execute asynchronously.

public async Task OnGetAsync()
{
    Student = await _context.Student.ToListAsync();
}
  • Das async-Schlüsselwort gibt dem Compiler folgende Anweisungen:The async keyword tells the compiler to:

    • Er soll Rückrufe für Teile des Methodentexts generieren.Generate callbacks for parts of the method body.
    • Er soll automatisch das Task-Objekt erstellen, das zurückgegeben wird.Automatically create the Task object that's returned. Weitere Informationen finden Sie unter Aufgabenrückgabetyp.For more information, see Task Return Type.
  • Der implizite Rückgabetyp Task steht für die derzeit ausgeführte Arbeit.The implicit return type Task represents ongoing work.

  • Das await-Schlüsselwort hat zur Folge, dass der Compiler die Methode in zwei Teile unterteilt.The await keyword causes the compiler to split the method into two parts. Der erste Teil endet mit dem Vorgang, der auf asynchrone Weise gestartet wird.The first part ends with the operation that's started asynchronously. Der zweite Teil wird in eine Rückrufmethode übertragen, die aufgerufen wird, wenn der Vorgang abgeschlossen wird.The second part is put into a callback method that's called when the operation completes.

  • Bei ToListAsync handelt es sich um die asynchrone Version der ToList-Erweiterungsmethode.ToListAsync is the asynchronous version of the ToList extension method.

Behalten Sie Folgendes im Hinterkopf, wenn Sie asynchronen Code schreiben, der Entity Framework Core verwendet:Some things to be aware of when writing asynchronous code that uses EF Core:

  • Es werden nur Anweisungen auf asynchrone Weise ausgeführt, die Abfragen oder Befehle auslösen, die an die Datenbank gesendet werden sollen.Only statements that cause queries or commands to be sent to the DB are executed asynchronously. Dazu gehören ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync und SaveChangesAsync.That includes, ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync, and SaveChangesAsync. Anweisungen wie var students = context.Students.Where(s => s.LastName == "Davolio"), die nur eine IQueryable-Instanz ändern, sind davon ausgeschlossen.It doesn't include statements that just change an IQueryable, such as var students = context.Students.Where(s => s.LastName == "Davolio").
  • Entity Framework Core-Kontexte sind nicht threadsicher. Versuchen Sie daher nicht, mehrere Vorgänge gleichzeitig auszuführen.An EF Core context isn't thread safe: don't try to do multiple operations in parallel.
  • Wenn Sie von den Leistungsvorteilen durch asynchronen Code profitieren möchten, überprüfen Sie, ob Bibliothekspakete (z.B. zum Paging) asynchronen Code verwenden, wenn sie Entity Framework Core-Methoden aufrufen, die Abfragen an die Datenbank senden.To take advantage of the performance benefits of async code, verify that library packages (such as for paging) use async if they call EF Core methods that send queries to the DB.

Weitere Informationen zur asynchronen Programmierung in .NET finden Sie unter Async (Übersicht) und Asynchrone Programmierung mit Async und Await (C#).For more information about asynchronous programming in .NET, see Async Overview and Asynchronous programming with async and await.

Im nächsten Tutorial erfahren Sie mehr über die CRUD-Vorgänge (Create, Read, Update, Delete = Erstellen, Lesen, Aktualisieren, Löschen).In the next tutorial, basic CRUD (create, read, update, delete) operations are examined.

Zusätzliche RessourcenAdditional resources