Ereignisse
Power BI DataViz Weltmeisterschaften
14. Feb., 16 Uhr - 31. März, 16 Uhr
Mit 4 Chancen, ein Konferenzpaket zu gewinnen und es zum LIVE Grand Finale in Las Vegas zu machen
Weitere InformationenDieser Browser wird nicht mehr unterstützt.
Führen Sie ein Upgrade auf Microsoft Edge durch, um die neuesten Features, Sicherheitsupdates und den technischen Support zu nutzen.
Von Tom Dykstra und Rick Anderson
In diesem Tutorial erfahren Sie die Grundlagen zu ASP.NET Core MVS und Entity Framework Core mit Controllern und Ansichten. Razor Pages ist ein alternatives Programmiermodell. Für neue Entwicklungsaufgaben wird empfohlen, Razor Pages mit MVC mit Controllern und Ansichten zu verwenden. Informationen finden Sie in der Razor Pages-Version dieses Tutorials. In jedem Tutorial werden einige Themen behandelt, die in den anderen Tutorials nicht behandelt werden:
Einige Aspekte, die in diesem MVC-Tutorial behandelt werden, nicht aber im Razor Pages-Tutorial:
Einige Aspekte, die im Razor Pages-Tutorial behandelt werden, nicht aber in diesem Tutorial:
Anhand der Beispiel-Web-App Contoso University wird veranschaulicht, wie Sie mit Entity Framework (EF) Core und Visual Studio eine MVC-Web-App in ASP.NET Core erstellen.
Bei der Beispiel-App handelt es sich um eine Website für die fiktive Contoso University. Sie enthält Funktionen wie die Zulassung von Studenten, die Erstellung von Kursen und Aufgaben von Dozenten. Dies ist das erste von mehreren Tutorials, in denen das Erstellen der Beispiel-App „Contoso University“ erläutert wird.
Dieses Tutorial wurde nicht für ASP.NET Core 6 oder höher aktualisiert. Die Anweisungen des Tutorials funktionieren nicht ordnungsgemäß, wenn Sie ein Projekt erstellen, das auf ASP.NET Core 6 oder höher ausgerichtet ist. Die Webvorlagen für ASP.NET Core 6 und höher verwenden z. B. das minimale Hostingmodell, in dem Startup.cs
und Program.cs
in einer einzelnen Program.cs
-Datei zusammengeführt werden.
Ein weiterer Unterschied in .NET 6 ist das NRT-Feature (Nullwerte zulassende Verweistypen). Die Projektvorlagen aktivieren dieses Feature standardmäßig. Probleme können auftreten, wenn EF eine Eigenschaft als erforderlich in .NET 6 betrachtet, die in .NET 5 Nullwerte zulässt. Beispielsweise tritt auf der Seite zum Erstellen von Kursteilnehmern ein Fehler auf, wenn die Eigenschaft Enrollments
so festgelegt wird, dass sie Nullwerte zulässt, oder das Hilfstag asp-validation-summary
nicht von ModelOnly
auf All
geändert wird.
Es wird empfohlen, das .NET 5 SDK für dieses Tutorial zu installieren und zu verwenden. Bis dieses Tutorial aktualisiert wird, lesen Sie Razor Pages mit Entity Framework Core in ASP.NET Core – Tutorial 1 von 8 zur Verwendung von Entity Framework mit ASP.NET Core 6 oder höher.
Die Visual Studio-Anweisungen verwenden SQL Server LocalDB, eine Version von SQL Server Express, die nur unter Windows ausgeführt werden kann.
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. Eine Liste mit häufig auftretenden Fehlern und den jeweiligen Lösungen finden Sie im Abschnitt zur Fehlerbehebung auf im letzten Tutorial dieser Tutorialreihe. Wenn Sie dort nicht die gewünschten Informationen finden, können Sie unter „StackOverflow.com“ für ASP.NET Core oder EF Core eine Frage posten.
Tipp
Diese Reihe besteht aus 10 Tutorials, die aufeinander aufbauen. Sie sollten jedes Mal, wenn Sie erfolgreich ein Tutorial abgeschlossen haben, eine Kopie des Projekts erstellen. Wenn Sie dann auf Probleme stoßen, können Sie zurück zum vorherigen Tutorial wechseln und müssen nicht wieder ganz von vorne beginnen.
Bei der App, die mithilfe dieser Tutorials erstellt werden soll, handelt es sich um eine einfache Website einer Universität.
Benutzer können Informationen zu den Studenten, Kursen und Dozenten abrufen. Im Folgenden finden Sie einige Screenshots der App:
ContosoUniversity
für Projektname ein. Es ist wichtig, genau diesen Namen unter Berücksichtigung der Groß-/Kleinschreibung zu verwenden, sodass beim Kopieren von Code jeder namespace
übereinstimmt.Ein paar grundlegende Änderungen gestalten das Menü der Website, das Layout und die Startseite.
Öffnen Sie Views/Shared/_Layout.cshtml
, und nehmen Sie die folgenden Änderungen vor:
ContosoUniversity
in Contoso University
. Diese Begriffskombination kommt dreimal vor.Die vorangehenden Änderungen sind im folgenden Code hervorgehoben:
<!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-controller="Home" asp-action="Index">Contoso University</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="About">About</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Students" asp-action="Index">Students</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Courses" asp-action="Index">Courses</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Instructors" asp-action="Index">Instructors</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Departments" asp-action="Index">Departments</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2020 - Contoso University - <a asp-area="" asp-controller="Home" asp-action="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>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Ersetzen Sie in Views/Home/Index.cshtml
den Inhalt der Datei durch folgendes Markup:
@{
ViewData["Title"] = "Home Page";
}
<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core MVC web application.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in a series of tutorials.</p>
<p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">See the tutorial »</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/main/aspnetcore/data/ef-mvc/intro/samples/5cu-final">See project source code »</a></p>
</div>
</div>
Drücken Sie STRG+F5, um das Projekt auszuführen, oder wählen Sie aus dem Menü Debuggen > Ohne Debuggen starten aus. Im Folgenden wird die Homepage mit den Registerkarten für die Seiten angezeigt, die in diesem Tutorial erstellt wurden.
In diesem Tutorial wird SQL Server verwendet, und das Anbieterpaket lautet Microsoft.EntityFrameworkCore.SqlServer.
Das EF-SQL Server-Paket und dessen Abhängigkeiten (Microsoft.EntityFrameworkCore
und Microsoft.EntityFrameworkCore.Relational
) stellen Runtimeunterstützung für EF bereit.
Fügen Sie das NuGet-Paket Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore hinzu. Geben Sie die folgenden Befehle in die Paket-Manager-Konsole (PMC) ein, um die NuGet-Pakete hinzuzufügen:
Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Das Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
NuGet-Paket stellt ASP.NET Core-Middleware für EF Core-Fehlerseiten bereit. Diese Middleware hilft bei der Erkennung und Diagnose von Fehlern bei EF Core-Migrationen.
Informationen zu anderen Datenbankanbietern, die für EF Core verfügbar sind, finden Sie unter Datenbankanbieter.
Die folgenden Entitätsklassen werden für diese App erstellt:
Die vorangehenden Entitäten weisen die folgenden Beziehungen auf:
Student
- und der Enrollment
-Entität: Ein Student kann für eine beliebige Anzahl von Kursen angemeldet werden.Course
- und der Enrollment
-Entität: Für jeden Kurs kann sich eine beliebige Anzahl von Studenten anmelden.In den folgenden Abschnitten wird für jede dieser Entitäten eine Klasse erstellt.
Erstellen Sie mit dem folgenden Code im Ordner Models (Modelle) die Student
-Klasse:
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 ist die Primärschlüsselspalte (PS) der Datenbanktabelle, die dieser Klasse entspricht. Standardmäßig interpretiert EF Core eine Eigenschaft mit dem Namen ID
oder classnameID
als Primärschlüssel. Beispielsweise kann der PS StudentID
anstatt ID
benannt werden.
Die Enrollments
-Eigenschaft ist eine Navigationseigenschaft. Navigationseigenschaften enthalten andere Entitäten, die dieser Entität zugehörig sind. Die Enrollments
-Eigenschaft einer Student
-Entität...:
Enrollment
-Entitäten, die mit dieser Student
-Entität verknüpft sind.Student
-Zeile in der Datenbank über zwei verknüpfte Enrollment
-Zeilen verfügt,...: Student
-Navigationseigenschaft dieser Enrollments
-Entität diese beiden Enrollment
-Entitäten.Enrollment
-Zeilen enthalten den PS-Wert eines Studierenden in der StudentID
-Fremdschlüsselspalte (FS).
Folgendes gilt, wenn eine Navigationseigenschaft mehrere Entitäten enthalten kann:
ICollection<T>
, List<T>
oder HashSet<T>
.M:n- und 1:n-Navigationsbeziehungen können mehrere Entitäten enthalten. Wenn ICollection<T>
verwendet wird, erstellt EF standardmäßig eine HashSet<T>
-Sammlung.
Erstellen Sie mit dem folgenden Code im Ordner Models (Modelle) die Enrollment
-Klasse:
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 PS. Diese Entität verwendet selbst das classnameID
-Muster anstelle von ID
. Die Student
-Entität hat das ID
-Muster verwendet. Einige Entwickler bevorzugen die Verwendung eines Musters im gesamten Datenmodell. In diesem Tutorial wird durch die Variation veranschaulicht, dass jedes Muster verwendet werden kann. In einem späteren Tutorial wird erläutert, wie Sie durch die Verwendung von ID
ohne Klassennamen die Vererbung einfacher in das Datenmodell implementieren.
Bei der Grade
-Eigenschaft handelt es sich um eine enum
. Das ?
nach der Grade
-Typdeklaration gibt an, dass die Grade
-Eigenschaft NULL-Werte zulässt. Eine Note mit dem Wert null
unterscheidet sich von einer Note mit dem Wert 0. null
bedeutet, dass eine Note noch nicht bekannt ist oder noch nicht zugewiesen wurde.
Bei der StudentID
-Eigenschaft handelt es sich um einen Fremdschlüssel (FS), und Student
ist die entsprechende Navigationseigenschaft. Die Enrollment
-Entität wird einer Student
-Entität zugewiesen. Das bedeutet, dass die Eigenschaft nur eine Student
-Entität enthalten kann. Dies unterscheidet sich von der Student.Enrollments
-Navigationseigenschaft, die mehrere Enrollment
-Entitäten enthalten kann.
Bei der CourseID
-Eigenschaft handelt es sich um einen FS, und Course
ist die entsprechende Navigationseigenschaft. Die Enrollment
-Entität wird einer Course
-Entität zugeordnet.
Entity Framework interpretiert eine Eigenschaft als eine FS-Eigenschaft, wenn Sie nach dem Schema <
Name der Navigationseigenschaft><
Name der Primärschlüsseleigenschaft>
benannt ist. Ein Beispiel hierfür wäre StudentID
für die Student
-Navigationseigenschaft, da Student
der PS der ID
-Entität ist. FS-Eigenschaften können auch nach dem <
Namen der Primärschlüsseleigenschaft>
benannt werden. Ein Beispiel hierfür wäre CourseID
, da Course
der PS der CourseID
-Entität ist.
Erstellen Sie mit dem folgenden Code im Ordner Models (Modelle) die Course
-Klasse:
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. Course
-Entitäten können sich auf jede beliebige Anzahl von Enrollment
-Entitäten beziehen.
Das DatabaseGenerated-Attribut wird in einem späteren Tutorial erläutert. Über dieses Attribut können Sie den PS für den Kurs angeben, anstatt ihn von der Datenbank generieren zu lassen.
Bei der Datenbankkontextklasse DbContext handelt es sich um die Hauptklasse, die die EF-Funktionen für ein angegebenes Datenmodell koordiniert. Diese Klasse wird durch Ableiten von der Microsoft.EntityFrameworkCore.DbContext
-Klasse erstellt. Die abgeleitete Klasse DbContext
gibt an, welche Entitäten im Datenmodell enthalten sind. Einige EF-Verhaltensweisen können angepasst werden. In diesem Projekt heißt die Klasse SchoolContext
.
Erstellen Sie im Projektordner einen Ordner mit dem Namen Data
(Daten).
Erstellen Sie im Ordner Data (Daten) mit dem folgenden Code eine SchoolContext
-Klasse:
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
}
}
Der vorangehende Code erstellt eine DbSet
-Eigenschaft für jede Entitätenmenge. In EF-Terminologie:
Die Anweisungen DbSet<Enrollment>
und DbSet<Course>
können auch weggelassen werden, wodurch sich nichts an der Funktionsweise ändert. EF würde sie aus folgenden Gründen implizit einschließen:
Student
-Entität verweist auf die Enrollment
-Entität.Enrollment
-Entität verweist auf die Course
-Entität.Wenn die Datenbank erstellt wird, erstellt EF Core Tabellen mit Namen, die den DbSet
-Eigenschaftennamen entsprechen. Eigenschaftennamen für Sammlungen stehen in der Regel im Plural. Beispielsweise wird Students
statt Student
verwendet. Entwickler sind sich uneinig darüber, ob Tabellennamen im Plural stehen sollten oder nicht. In diesen Tutorials wird das Standardverhalten außer Kraft gesetzt, indem Tabellennamen im DbContext
im Singular angegeben werden. Fügen Sie dafür den hervorgehobenen Code nach der DbSet-Eigenschaft ein.
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}
Dependency Injection ist in ASP.NET Core enthalten. Dienste wie der EF-Datenbankkontext werden per Dependency Injection beim App-Start registriert. Für Komponenten, die diese Dienste benötigen (z. B. MVC-Controller), werden sie über Konstruktorparameter bereitgestellt. Der Code des Controllerkonstruktors, der eine Kontextinstanz abruft, wird später in diesem Tutorial gezeigt.
Öffnen Sie SchoolContext
, und fügen Sie der Startup.cs
-Methode die hervorgehobenen Zeilen hinzu, um ConfigureServices
als Dienst zu registrieren.
using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ContosoUniversity
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
}
Der Name der Verbindungszeichenfolge wird an den Kontext übergeben, indem Sie eine Methode auf einem DbContextOptionsBuilder
-Objekt aufrufen. Für die lokale Entwicklung liest das ASP.NET Core-Konfigurationssystem die Verbindungszeichenfolge aus der appsettings.json
-Datei.
Öffnen Sie die appsettings.json
-Datei, und fügen Sie wie im folgenden Markup dargestellt eine Verbindungszeichenfolge hinzu:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Fügen Sie AddDatabaseDeveloperPageExceptionFilter in ConfigureServices
hinzu, wie im folgenden Code dargestellt:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddControllersWithViews();
}
AddDatabaseDeveloperPageExceptionFilter
bietet hilfreiche Fehlerinformationen in der Entwicklungsumgebung.
Die Verbindungszeichenfolge gibt SQL Server LocalDB an. 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 wird bedarfsgesteuert gestartet und im Benutzermodus ausgeführt, sodass keine komplexe Konfiguration anfällt. Standardmäßig erstellt LocalDB .mdf-Datenbankdateien im C:/Users/<user>
-Verzeichnis.
EF erstellt eine leere Datenbank. In diesem Abschnitt wird eine Methode hinzugefügt, die aufgerufen wird, nachdem die Datenbank erstellt wurde, um diese mit Testdaten zu befüllen.
Mithilfe der EnsureCreated
-Methode wird die Datenbank automatisch erstellt. In einem späteren Tutorial wird dargestellt, wie Sie mit Änderungen an dem Modell umgehen können, indem Sie Code First-Migrationen verwenden, um das Datenbankschema zu verwenden, anstatt die Datenbank zu verwerfen und neu zu erstellen.
Erstellen Sie im Ordner Data (Daten) mit dem folgenden Code eine neue Klasse mit dem Namen DbInitializer
:
using ContosoUniversity.Models;
using System;
using System.Linq;
namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();
// Look for any students.
if (context.Students.Any())
{
return; // DB has been seeded
}
var students = new Student[]
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();
var courses = new Course[]
{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();
var enrollments = new Enrollment[]
{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollments.Add(e);
}
context.SaveChanges();
}
}
}
Der vorangehende Code überprüft, ob die Datenbank vorhanden ist:
List<T>
-Auflistungen geladen, um die Leistung zu optimieren.Aktualisieren Sie Program.cs
mit folgendem Code:
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>();
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>();
});
}
}
Program.cs
führt beim Starten der App folgende Schritte durch:
DbInitializer.Initialize
-Methode auf.Initialize
-Methode, wie im folgenden Code dargestellt:public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<SchoolContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
Wenn die App zum ersten Mal ausgeführt wird, wird die Datenbank erstellt und mit Testdaten geladen. Führen Sie bei jeder Datenmodelländerung folgende Schritte durch:
In späteren Tutorials wird die Datenbank angepasst, wenn das Datenmodell geändert wird, ohne sie zu löschen und neu zu erstellen. Wenn das Datenmodell geändert wird, gehen keine Daten verloren.
Verwenden Sie die Gerüstbau-Engine in Visual Studio, um einen MVC-Controller und Ansichten hinzuzufügen, die EF zum Abfragen und Speichern von Daten verwenden.
Die automatische Erstellung von CRUD-Aktionsmethoden und Ansichten wird als Gerüstbau bezeichnet.
Controllers
, und wählen Sie Hinzufügen > Neues Gerüstelement aus.Die Gerüstbau-Engine von Visual Studio erstellt eine StudentsController.cs
-Datei und mehrere Ansichten (*.cshtml
-Dateien), die mit dem Controller zusammenarbeiten.
Beachten Sie, dass der Controller SchoolContext
als Konstruktorparameter verwendet.
namespace ContosoUniversity.Controllers
{
public class StudentsController : Controller
{
private readonly SchoolContext _context;
public StudentsController(SchoolContext context)
{
_context = context;
}
Über die Abhängigkeitsinjektion in ASP.NET Core wird eine Instanz von SchoolContext
an den Controller übergeben. Dies haben Sie in der Startup
-Klasse konfiguriert.
Der Controller enthält eine Index
-Aktionsmethode, über die alle Studenten in der Datenbank angezeigt werden. Die Methode ruft eine Listen von Studenten aus der Entitätenmenge „Student“ ab, indem sie die Students
-Eigenschaft aus der Datenbankkontextinstanz liest:
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
Die Elemente der asynchronen Programmierung in diesem Code werden später im Tutorial erläutert.
In der Views/Students/Index.cshtml
-Ansicht wird diese Liste in einer Tabelle dargestellt:
@model IEnumerable<ContosoUniversity.Models.Student>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
@Html.DisplayNameFor(model => model.EnrollmentDate)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Drücken Sie STRG+F5, um das Projekt auszuführen, oder wählen Sie aus dem Menü Debuggen > Ohne Debuggen starten aus.
Klicken Sie auf die Registerkarte „Students“, um die Testdaten abzurufen, die über die DbInitializer.Initialize
-Methode eingefügt wurden. Je nachdem, wie klein Ihr Browserfenster dargestellt wird, sehen Sie einen Students
-Registerkartenlink unten auf der Seite, oder Sie müssen auf das Navigationssymbol in der oberen rechten Ecke klicken, damit der Link angezeigt wird.
Wenn die App gestartet wird, ruft die DbInitializer.Initialize
-Methode EnsureCreated
auf. EF hat festgestellt, dass keine Datenbank vorhanden war:
Initialize
-Methode hat die Datenbank mit Daten befüllt.Verwenden Sie den SQL Server-Objekt-Explorer (SSOX), um die Datenbank in Visual Studio anzuzeigen:
ContosoUniversity1
aus, den Eintrag für den Datenbanknamen in der Verbindungszeichenfolge in der appsettings.json
-Datei.Klicken Sie mit der rechten Maustaste auf die Tabelle Student, und klicken Sie auf Daten anzeigen, um die Daten in der Tabelle anzuzeigen.
Die Datenbankdateien *.mdf
und *.ldf
befinden sich im Ordner C:\Benutzer\<Benutzername>.
Da EnsureCreated
in der Initialisierermethode aufgerufen wird, die beim App-Start ausgeführt wird, können Sie folgende Aktionen ausführen:
Student
-Klasse vornehmen.Wenn der EmailAddress
-Klasse beispielsweise eine Student
-Eigenschaft hinzugefügt wurde, wird in der neu erstellten Tabelle eine EmailAddress
-Spalte angezeigt. Die Ansicht zeigt die neue EmailAddress
-Eigenschaft nicht an.
Da die Konventionen von EF verwendet werden, ist nicht viel geschriebener Code nötig, damit EF eine vollständige Datenbank erstellt:
DbSet
-Eigenschaften werden als Tabellennamen verwendet. Für Entitäten, auf die nicht über eine DbSet
-Eigenschaft verwiesen wird, werden Entitätsklassennamen als Tabellennamen verwendet.ID
oder classnameID
werden als PS-Eigenschaften erkannt.<
Name der Navigationseigenschaft><
Name der Primärschlüsseleigenschaft>
benannt ist. Ein Beispiel hierfür wäre StudentID
für die Student
-Navigationseigenschaft, da Student
der PS der ID
-Entität ist. FS-Eigenschaften können auch nach dem <
Namen der Primärschlüsseleigenschaft>
benannt werden. Ein Beispiel hierfür wäre EnrollmentID
, da Enrollment
der PS der EnrollmentID
-Entität ist.Konventionelles Verhalten kann überschrieben werden. Beispielsweise können Tabellennamen wie in diesem Tutorial bereits gezeigt explizit angegeben werden. Spaltennamen und eine beliebige Eigenschaft können als PS oder FS festgelegt werden.
Die asynchrone Programmierung ist der Standardmodus für ASP.NET Core und 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. Wenn dies der Fall ist, kann der Server keine neuen Anforderungen verarbeiten, bis die Threads wieder freigegeben werden. 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. 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. 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.
Durch die Verwendung von asynchronem Code entsteht ein geringes Maß an Mehraufwand zur Laufzeit. In Situationen, in denen nur wenig Datenverkehr verarbeitet werden muss, 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.
Im folgenden Code führen async
, Task<T>
, await
und ToListAsync
dazu, dass der Code asynchron ausgeführt wird.
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
async
-Schlüsselwort teilt dem Compiler mit, dass er für einzelne Teile des Methodentexts Rückrufe generieren und das zurückgegebene Task<IActionResult>
-Objekt automatisch erstellen soll.Task<IActionResult>
stellt derzeit ausgeführte Arbeiten mit dem Ergebnis von Typ IActionResult
dar.await
-Schlüsselwort hat zur Folge, dass der Compiler die Methode in zwei Teile unterteilt. Der erste Teil endet mit dem Vorgang, der auf asynchrone Weise gestartet wird. Der zweite Teil wird in eine Rückrufmethode übertragen, die aufgerufen wird, wenn der Vorgang abgeschlossen wird.ToListAsync
handelt es sich um die asynchrone Version der ToList
-Erweiterungsmethode.Denken Sie an Folgendes, wenn Sie asynchronen Code schreiben, in dem EF verwendet wird:
ToListAsync
, SingleOrDefaultAsync
und SaveChangesAsync
ein. Anweisungen wie IQueryable
, die nur eine var students = context.Students.Where(s => s.LastName == "Davolio")
-Instanz ändern, sind beispielsweise davon ausgeschlossen.await
-Schlüsselwort verwenden.Weitere Informationen zur asynchronen Programmierung in .NET finden Sie unter Async (Übersicht).
Weitere Informationen zum Begrenzen der Anzahl von Entitäten, die infolge einer Abfrage zurückgegeben werden, finden Sie unter Überlegungen zur Leistung.
Die Konfiguration der Protokollierung wird meistens im Abschnitt Logging
der appsettings.{Environment}.json
-Dateien angegeben. Um SQL Anweisungen zu protokollieren, fügen Sie "Microsoft.EntityFrameworkCore.Database.Command": "Information"
der Datei appsettings.Development.json
hinzu:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDB-2;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
,"Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
},
"AllowedHosts": "*"
}
Mit dem obigen JSON-Code werden SQL Anweisungen in der Befehlszeile und im Visual Studio Ausgabefenster angezeigt.
Weitere Informationen finden Sie im Artikel zum Protokollieren in .NET Core und ASP.NET Core und in diesem GitHub-Issue.
Fahren Sie mit dem nächsten Tutorial fort, um zu erfahren, wie Sie grundlegende CRUD-Vorgänge (Create, Read, Update, Delete = Erstellen, Lesen, Aktualisieren, Löschen) ausführen.
In diesem Tutorial erfahren Sie die Grundlagen zu ASP.NET Core MVS und Entity Framework Core mit Controllern und Ansichten. Razor Pages ist ein alternatives Programmiermodell. Für neue Entwicklungsaufgaben wird empfohlen, Razor Pages mit MVC mit Controllern und Ansichten zu verwenden. Informationen finden Sie in der Razor Pages-Version dieses Tutorials. In jedem Tutorial werden einige Themen behandelt, die in den anderen Tutorials nicht behandelt werden:
Einige Aspekte, die in diesem MVC-Tutorial behandelt werden, nicht aber im Razor Pages-Tutorial:
Einige Aspekte, die im Razor Pages-Tutorial behandelt werden, nicht aber in diesem Tutorial:
Die Beispielwebanwendung der Contoso University veranschaulicht, wie mit Entity Framework (EF) Core 2.2 und Visual Studio 2019 ASP.NET Core MVC-Webanwendungen erstellt werden.
Dieses Tutorial wurde nicht für ASP.NET Core 3.1 aktualisiert. Es wurde für ASP.NET Core 5.0 aktualisiert.
Bei der Beispiel-App handelt es sich um eine Website für die fiktive Contoso University. Sie enthält Funktionen wie die Zulassung von Studenten, die Erstellung von Kursen und Aufgaben von Dozenten. Dies ist die erste Tutorial in der Reihe, in dem die Erstellung der Beispielanwendung der Contoso University von Grund auf erläutert wird.
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. Eine Liste mit häufig auftretenden Fehlern und den jeweiligen Lösungen finden Sie im Abschnitt zur Fehlerbehebung auf im letzten Tutorial dieser Tutorialreihe. Wenn Sie dort nicht die gewünschten Informationen finden, können Sie unter „StackOverflow.com“ für ASP.NET Core oder EF Core eine Frage posten.
Tipp
Diese Reihe besteht aus 10 Tutorials, die aufeinander aufbauen. Sie sollten jedes Mal, wenn Sie erfolgreich ein Tutorial abgeschlossen haben, eine Kopie des Projekts erstellen. Wenn Sie dann auf Probleme stoßen, können Sie zurück zum vorherigen Tutorial wechseln und müssen nicht wieder ganz von vorne beginnen.
Bei der Anwendung, die Sie mithilfe dieser Tutorials erstellen, handelt es sich um eine einfache Universitätswebsite.
Benutzer können Informationen zu den Studenten, Kursen und Dozenten abrufen. Nachfolgend werden einige Anzeigen dargestellt, die erstellt werden sollen.
Öffnen Sie Visual Studio.
Klicken Sie im Menü Datei auf Neu > Projekt.
Wählen Sie im linken Bereich Installiert > Visual C# > Web aus.
Wählen Sie die Projektvorlage ASP.NET Core-Webanwendung aus.
Geben Sie ContosoUniversity als Name ein, und klicken Sie auf OK.
Warten Sie, bis das Dialogfeld Neue ASP.NET Core-Webanwendung angezeigt wird.
Wählen Sie .NET Core, ASP.NET Core 2.2 und die Vorlage Webanwendung (Model-View-Controller) aus.
Stellen Sie sicher, dass Authentifizierung auf Keine Authentifizierung festgelegt ist.
Wählen Sie OK aus.
Einige einfache Änderungen richten das Websitemenü, das Layout und die Startseite ein.
Öffnen Sie Views/Shared/_Layout.cshtml
, und nehmen Sie die folgenden Änderungen vor:
Ändern Sie jedes „ContosoUniversity“ in „Contoso University“. Diese Begriffskombination kommt dreimal vor.
Fügen Sie Menüeinträge für About (Informationen), Students (Studierende), Courses (Kurse), Instructors (Dozent*innen) und Departments (Abteilungen) hinzu, und löschen Sie den Menüeintrag Privacy (Privatsphäre).
Die Änderungen werden hervorgehoben.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Contoso University</title>
<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
crossorigin="anonymous"
integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
</environment>
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Contoso University</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="About">About</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Students" asp-action="Index">Students</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Courses" asp-action="Index">Courses</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Instructors" asp-action="Index">Instructors</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Departments" asp-action="Index">Departments</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<partial name="_CookieConsentPartial" />
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2019 - Contoso University - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"
asp-fallback-src="~/lib/jquery/dist/jquery.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
</script>
</environment>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
Ersetzen Sie den Inhalt der Datei Views/Home/Index.cshtml
durch den folgenden Code, um den Text über ASP.NET und MVC durch Text über diese Anwendung zu ersetzen:
@{
ViewData["Title"] = "Home Page";
}
<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core MVC web application.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in a series of tutorials.</p>
<p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">See the tutorial »</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/main/aspnetcore/data/ef-mvc/intro/samples/cu-final">See project source code »</a></p>
</div>
</div>
Drücken Sie STRG+F5, um das Projekt auszuführen, oder wählen Sie aus dem Menü Debuggen > Ohne Debuggen starten aus. Dann wird Ihnen die Startseite mit Registerkarten für die Seiten angezeigt, die Sie mithilfe dieses Tutorials erstellen.
Installieren Sie den Datenbankanbieter, der verwendet werden soll, um einem Projekt EF Core-Unterstützung hinzuzufügen. In diesem Tutorial wird SQL Server verwendet, und das Anbieterpaket lautet Microsoft.EntityFrameworkCore.SqlServer. Dieses Paket ist im Microsoft.AspNetCore.App-Metapaket enthalten, weshalb Sie nicht auf das Paket verweisen müssen.
Das EF SQL Server-Paket und dessen Abhängigkeiten (Microsoft.EntityFrameworkCore
und Microsoft.EntityFrameworkCore.Relational
) stellen für EF Runtimeunterstützung bereit. Sie fügen später im Laufe des Migrations-Tutorials ein Paket mit Tools hinzu.
Informationen zu anderen Datenbankanbietern, die für Entity Framework Core verfügbar sind, finden Sie unter Datenbankanbieter.
Als nächstes erstellen Sie Entitätsklassen für die Contoso University-Anwendung. Beginnen Sie mit dem folgenden drei Entitäten.
Es besteht eine 1:n-Beziehung zwischen den Entitäten Student
und Enrollment
. Außerdem besteht eine 1:n-Beziehung zwischen den Entitäten Course
und Enrollment
. Das bedeutet, dass ein Student für beliebig viele Kurse angemeldet sein kann und sich für jeden Kurs eine beliebige Anzahl von Studenten anmelden kann.
In den folgenden Abschnitten erstellen Sie für jede dieser Entitäten eine Klasse.
Erstellen Sie im Ordner Models (Modelle) die Klassendatei Student.cs
, und ersetzen Sie den Vorlagencode durch folgenden 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. Standardmäßig interpretiert Entity Framework Core eine Eigenschaft mit dem Namen ID
oder classnameID
als Primärschlüssel.
Die Enrollments
-Eigenschaft ist eine Navigationseigenschaft. Navigationseigenschaften enthalten andere Entitäten, die dieser Entität zugehörig sind. In diesem Fall enthält die Enrollments
-Eigenschaft einer Student entity
all diese Enrollment
-Entitäten, die mit der Student
-Entität in Zusammenhang stehen. Das heißt: Wenn eine Student
-Zeile in der Datenbank über zwei zugehörige Enrollment
-Zeilen verfügt (Zeilen, in denen der Primärschlüsselwert dieses Studierenden in der StudentID-Fremdschlüsselspalte enthalten ist), enthält die Student
-Navigationseigenschaft dieser Enrollments
-Entität diese beiden Enrollment
-Entitäten.
Wenn eine Navigationseigenschaft mehrere Entitäten enthalten kann (wie bei m:n- oder 1:n-Beziehungen), muss dessen Typ aus einer Liste bestehen, in der Einträge hinzugefügt, gelöscht und aktualisiert werden können – z.B.: ICollection<T>
. Sie können die ICollection<T>
-Instanz oder einen Typ wie List<T>
oder HashSet<T>
angeben. Wenn Sie ICollection<T>
angeben, erstellt EF standardmäßig eine HashSet<T>
-Auflistung.
Erstellen Sie im Ordner Models (Modelle) die Datei Enrollment.cs
, und ersetzen Sie den vorhandenen Code durch folgenden 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 wird als Primärschlüssel verwendet. Diese Entität verwendet das classnameID
-Muster anstelle der ID
alleine, wie in der Student
-Entität dargestellt wurde. Normalerweise würden Sie nur ein Muster auswählen und dieses für das gesamte Datenmodell verwenden. Diese Variation soll verdeutlichen, dass Sie ein beliebiges Muster erstellen können. 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.
Bei der Grade
-Eigenschaft handelt es sich um eine enum
. Das Fragezeichen nach der Grade
-Typdeklaration gibt an, dass die Grade
-Eigenschaft NULL-Werte zulässt. 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.
Bei der StudentID
-Eigenschaft handelt es sich um einen Fremdschlüssel, und Student
ist die entsprechende Navigationseigenschaft. Eine Enrollment
-Entität wird einer Student
-Entität zugeordnet, damit die Eigenschaft nur eine Student
-Entität enthalten kann. Dies steht im Gegensatz zu der bereits erläuterten Student.Enrollments
-Navigationseigenschaft, die mehrere Enrollment
-Entitäten enthalten kann.
Bei der CourseID
-Eigenschaft handelt es sich um einen Fremdschlüssel, und Course
ist die entsprechende Navigationseigenschaft. Die Enrollment
-Entität wird einer Course
-Entität zugeordnet.
Entity Framework interpretiert Eigenschaften als Fremdschlüsseleigenschaften, wenn Sie den Namen <navigation property name><primary key property name>
haben – z.B. StudentID
für die Student
-Navigationseigenschaft, da der Primärschlüssel der Student
-Entität ID
lautet. Fremdschlüsseleigenschaften können auch einfach den Namen <primary key property name>
haben – z.B. CourseID
, da der Primärschlüssel der Course
-Entität CourseID
lautet.
Erstellen Sie im Ordner Models (Modelle) die Datei Course.cs
, und ersetzen Sie den vorhandenen Code durch folgenden 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. Course
-Entitäten können sich auf jede beliebige Anzahl von Enrollment
-Entitäten beziehen.
Weitere Informationen zum DatabaseGenerated
-Attribut erhalten Sie in einem späteren Tutorial dieser Reihe. Im Grunde können Sie über dieses Attribut den Primärschlüssel für den Kurs angeben, anstatt ihn von der Datenbank generieren zu lassen.
Die Datenbankkontextklasse ist die Hauptklasse, die die Entity Framework-Funktionen für ein angegebenes Datenmodell koordiniert. Sie können diese Klasse durch Ableiten von der Microsoft.EntityFrameworkCore.DbContext
-Klasse erstellen. Sie geben in Ihrem Code an, welche Entitäten im Datenmodell enthalten sind. Außerdem können Sie bestimmte Entity Framework-Verhalten anpassen. In diesem Projekt heißt die Klasse SchoolContext
.
Erstellen Sie im Projektordner einen Ordner mit dem Namen Data (Daten).
Erstellen Sie im Ordner Data (Daten) die Klassendatei SchoolContext.cs
, und ersetzen Sie den Vorlagencode durch folgenden Code:
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
}
}
Dieser Code erstellt eine DbSet
-Eigenschaft für jede Entitätenmenge. In der Terminologie von Entity Framework entspricht eine Entitätenmenge in der Regel einer Datenbanktabelle, und eine Entität entspricht einer Zeile in einer Tabelle.
Auch wenn Sie die Anweisungen DbSet<Enrollment>
und DbSet<Course>
auslassen, ändert dies nichts an der Funktionsweise. Diese sind implizit in Entity Framework enthalten, da die Student
-Entität auf die Enrollment
-Entität und die Enrollment
-Entität auf die Course
-Entität verweist.
Wenn die Datenbank erstellt wird, erstellt EF Core Tabellen mit Namen, die den DbSet
-Eigenschaftennamen entsprechen. Eigenschaftennamen für Auflistungen stehen in der Regel im Plural (Students anstelle von Student). Allerdings sind sich Entwickler uneinig darüber, ob auch Tabellennamen im Plural stehen sollten. In diesen Tutorials wird das Standardverhalten außer Kraft gesetzt, indem im DbContext Tabellennamen im Singular angegeben werden. Fügen Sie dafür den hervorgehobenen Code nach der DbSet-Eigenschaft ein.
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}
Erstellen Sie das Projekt, um zu ermitteln, ob Compilerfehler vorliegen.
ASP.NET Core implementiert standardmäßig Dependency Injection. Dienste wie der EF-Datenbankkontext werden per Dependency Injection beim Anwendungsstart registriert. Komponenten, die diese Dienste erfordern (z.B. Ihre MVC-Controller), werden über Konstruktorparameter bereitgestellt. Nachfolgend in diesem Tutorial wird der Konstruktorcode des Controllers angezeigt, der eine Kontextinstanz abruft.
Öffnen Sie SchoolContext
, und fügen Sie der Startup.cs
-Methode die hervorgehobenen Zeilen hinzu, um ConfigureServices
als Dienst zu registrieren.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
}
Der Name der Verbindungszeichenfolge wird an den Kontext übergeben, indem Sie eine Methode auf einem DbContextOptionsBuilder
-Objekt aufrufen. Für die lokale Entwicklung liest das ASP.NET Core-Konfigurationssystem die Verbindungszeichenfolge aus der appsettings.json
-Datei.
Fügen Sie using
-Anweisungen für die Namespaces ContosoUniversity.Data
und Microsoft.EntityFrameworkCore
hinzu, und erstellen Sie dann das Projekt.
using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;
Öffnen Sie die appsettings.json
-Datei, und fügen Sie wie im folgenden Beispiel dargestellt eine Verbindungszeichenfolge hinzu.
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
Die Verbindungszeichenfolge gibt eine SQL Server-LocalDB-Datenbank an. LocalDB ist eine Basisversion der SQL Server Express-Datenbank-Engine, die zwar zur Anwendungsentwicklung, aber nicht für den Produktionseinsatz bestimmt ist. LocalDB wird bedarfsgesteuert gestartet und im Benutzermodus ausgeführt, sodass keine komplexe Konfiguration anfällt. Standardmäßig erstellt LocalDB .mdf-Datenbankdateien im C:/Users/<user>
-Verzeichnis.
Entity Framework erstellt eine leere Datenbank für Sie. In diesem Abschnitt schreiben Sie eine Methode, die aufgerufen wird, nachdem die Datenbank erstellt wurde, um diese mit Testdaten aufzufüllen.
Verwenden Sie an dieser Stelle die EnsureCreated
-Methode, um die Datenbank automatisch zu erstellen. In einem späteren Tutorial wird dargestellt, wie Sie mit Änderungen an dem Modell umgehen können, indem Sie Code First-Migrationen verwenden, um das Datenbankschema zu verwenden, anstatt die Datenbank zu verwerfen und neu zu erstellen.
Erstellen Sie im Ordner Data (Daten) eine neue Klassendatei mit dem Namen DbInitializer.cs
, und ersetzen Sie den Vorlagencode durch den folgenden Code, wodurch, falls nötig, eine Datenbank erstellt wird und Testdaten in eine neue Datenbank geladen werden.
using ContosoUniversity.Models;
using System;
using System.Linq;
namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();
// Look for any students.
if (context.Students.Any())
{
return; // DB has been seeded
}
var students = new Student[]
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();
var courses = new Course[]
{
new Course{CourseID=1050,Title="Chemistry",Credits=3},
new Course{CourseID=4022,Title="Microeconomics",Credits=3},
new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
new Course{CourseID=1045,Title="Calculus",Credits=4},
new Course{CourseID=3141,Title="Trigonometry",Credits=4},
new Course{CourseID=2021,Title="Composition",Credits=3},
new Course{CourseID=2042,Title="Literature",Credits=4}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();
var enrollments = new Enrollment[]
{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollments.Add(e);
}
context.SaveChanges();
}
}
}
Der Code überprüft, ob Studenten in der Datenbank enthalten sind. Wenn dies nicht der Fall ist, nimmt diese an, dass die Datenbank neu ist und mit Testdaten aufgefüllt werden muss. Testdaten werden in Arrays anstelle von List<T>
-Auflistungen geladen, um die Leistung zu optimieren.
Ändern Sie in Program.cs
die Main
-Methode, um beim Anwendungsstart die folgenden Vorgänge auszuführen:
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>();
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>();
});
}
}
Wenn die Anwendung zum ersten Mal ausgeführt wird, wird die Datenbank erstellt und mit Testdaten befüllt. Führen Sie bei jeder Datenmodelländerung folgende Schritte durch:
In späteren Tutorials wird ein Update für die Datenbank ausgeführt, wenn das Datenmodell geändert wird, ohne die Datenbank zu löschen und neu zu erstellen.
In diesem Abschnitt wird die Gerüstbau-Engine in Visual Studio verwendet, um einen MVC-Controller und Ansichten hinzuzufügen, die EF zum Abfragen und Speichern von Daten verwenden.
Die automatische Erstellung von CRUD-Aktionsmethoden und Ansichten wird als Gerüstbau bezeichnet. Gerüstbau und Codegeneration unterscheiden sich insofern als der Gerüstbaucode ein Startpunkt ist, den Sie Ihren eigenen Anforderungen entsprechend verändern können. Generierter Code wird in der Regel nicht verändert. Wenn Sie generierten Code anpassen müssen, verwenden Sie partielle Klassen, oder generieren Sie den Code erneut, wenn Änderungen vorgenommen werden.
Die Gerüstbau-Engine von Visual Studio erstellt eine StudentsController.cs
-Datei und mehrere Ansichten (.cshtml
-Dateien), die mit dem Controller zusammenarbeiten.
Beachten Sie, dass der Controller SchoolContext
als Konstruktorparameter verwendet.
namespace ContosoUniversity.Controllers
{
public class StudentsController : Controller
{
private readonly SchoolContext _context;
public StudentsController(SchoolContext context)
{
_context = context;
}
Über die Abhängigkeitsinjektion in ASP.NET Core wird eine Instanz von SchoolContext
an den Controller übergeben. Dies wurde in der Datei Startup.cs
konfiguriert.
Der Controller enthält eine Index
-Aktionsmethode, über die alle Studenten in der Datenbank angezeigt werden. Die Methode ruft eine Listen von Studenten aus der Entitätenmenge „Student“ ab, indem sie die Students
-Eigenschaft aus der Datenbankkontextinstanz liest:
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
Später im Tutorial erfahren Sie mehr über die Elemente der asynchronen Programmierung in diesem Code.
In der Views/Students/Index.cshtml
-Ansicht wird diese Liste in einer Tabelle dargestellt:
@model IEnumerable<ContosoUniversity.Models.Student>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
@Html.DisplayNameFor(model => model.EnrollmentDate)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Drücken Sie STRG+F5, um das Projekt auszuführen, oder wählen Sie aus dem Menü Debuggen > Ohne Debuggen starten aus.
Klicken Sie auf die Registerkarte „Students“, um die Testdaten abzurufen, die über die DbInitializer.Initialize
-Methode eingefügt wurden. Je nachdem, wie klein Ihr Browserfenster dargestellt wird, sehen Sie einen Students
-Registerkartenlink unten auf der Seite, oder Sie müssen auf das Navigationssymbol in der oberen rechten Ecke klicken, damit der Link angezeigt wird.
Nachdem Sie die Anwendung gestartet haben, ruft die DbInitializer.Initialize
-Methode EnsureCreated
auf. EF hat festgestellt, dass noch keine Datenbank vorhanden war und hat deshalb eine erstellt. Anschließend hat der restliche Initialize
-Methodencode die Datenbank mit Daten aufgefüllt. Sie können den SQL Server-Objekt-Explorer (SSOX) verwenden, um die Datenbank in Visual Studio abzurufen.
Schließen Sie den Browser.
Wenn das SSOX-Fenster noch nicht geöffnet ist, wählen Sie es aus dem Menü Ansicht in Visual Studio aus.
Klicken Sie im SSOX auf (localdb)\MSSQLLocalDB > Datenbanken und dann auf den Eintrag zu dem Datenbanknamen, der sich in der Verbindungszeichenfolge in der appsettings.json
-Datei befindet.
Erweitern Sie den Knoten Tabellen, um die Tabellen in der Datenbank anzuzeigen.
Klicken Sie mit der rechten Maustaste auf die Tabelle Students, und klicken Sie auf Daten anzeigen, um die erstellten Spalten und die in die Tabelle eingefügten Zeilen aufzurufen.
Die Datenbankdateien im Format MDF und LDF befinden sich im Ordner C:\Benutzer<Benutzername>.
Da Sie EnsureCreated
in der Initialisierermethode aufrufen, die beim App-Start ausgeführt wird, können Sie Änderungen an der Student
-Klasse vornehmen, die Datenbank löschen oder die Anwendung erneut ausführen. Dann wird Ihre Datenbank automatisch Ihren Änderungen entsprechend neu erstellt. Wenn Sie z.B. eine EmailAddress
-Eigenschaft zu der Student
-Klasse hinzufügen, wird eine neue EmailAddress
-Spalte in der neu erstellten Tabelle angezeigt.
Sie mussten nur wenig Code schreiben, damit Entity Framework eine vollständige Datenbank erstellen kann, da Konventionen oder Annahmen von Entity Framework verwendet werden.
DbSet
-Eigenschaften werden als Tabellennamen verwendet. Für Entitäten, auf die nicht über eine DbSet
-Eigenschaft verwiesen wird, werden Entitätsklassennamen als Tabellennamen verwendet.StudentID
für die Student
-Navigationseigenschaft, da der Primärschlüssel der Student
-Entität ID
lautet). Fremdschlüsseleigenschaften können auch einfach den Namen <Eigenschaftenname des Primärschlüssels> haben (z. B. EnrollmentID
, da der Primärschlüssel derEnrollment
-Entität EnrollmentID
lautet).Konventionelles Verhalten kann überschrieben werden. Beispielsweise können Sie, wie bereits in diesem Tutorial erläutert, Tabellennamen explizit angeben. Außerdem können Sie Spaltennamen und jede beliebige Eigenschaft als Primär- oder Fremdschlüssel festlegen. Dies wird in einem späteren Tutorial in dieser Reihe erläutert.
Die asynchrone Programmierung ist der Standardmodus für ASP.NET Core und 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. Wenn dies der Fall ist, kann der Server keine neuen Anforderungen verarbeiten, bis die Threads wieder freigegeben werden. 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. 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. 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.
Durch die Verwendung von asynchronem Code entsteht ein geringes Maß an Mehraufwand zur Laufzeit. In Situationen, in denen nur wenig Datenverkehr verarbeitet werden muss, 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.
Im folgenden Code haben das async
-Schlüsselwort, der Task<T>
-Rückgabewert, das await
-Schlüsselwort und die ToListAsync
-Methode zur Folge, dass der Code auf asynchrone Weise ausgeführt wird.
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
async
-Schlüsselwort teilt dem Compiler mit, dass er für einzelne Teile des Methodentexts Rückrufe generieren und das zurückgegebene Task<IActionResult>
-Objekt automatisch erstellen soll.Task<IActionResult>
stellt derzeit ausgeführte Arbeiten mit dem Ergebnis von Typ IActionResult
dar.await
-Schlüsselwort hat zur Folge, dass der Compiler die Methode in zwei Teile unterteilt. Der erste Teil endet mit dem Vorgang, der auf asynchrone Weise gestartet wird. Der zweite Teil wird in eine Rückrufmethode übertragen, die aufgerufen wird, wenn der Vorgang abgeschlossen wird.ToListAsync
handelt es sich um die asynchrone Version der ToList
-Erweiterungsmethode.Behalten Sie Folgendes im Hinterkopf, wenn Sie asynchronen Code schreiben, der Entity Framework Core verwendet:
ToListAsync
, SingleOrDefaultAsync
und SaveChangesAsync
ein. Anweisungen wie IQueryable
, die nur eine var students = context.Students.Where(s => s.LastName == "Davolio")
-Instanz ändern, sind beispielsweise davon ausgeschlossen.await
-Schlüsselwort verwenden.Weitere Informationen zur asynchronen Programmierung in .NET finden Sie unter Async (Übersicht).
Fahren Sie mit dem nächsten Tutorial fort, um zu erfahren, wie Sie grundlegende CRUD-Vorgänge (Create, Read, Update, Delete = Erstellen, Lesen, Aktualisieren, Löschen) ausführen.
Feedback zu ASP.NET Core
ASP.NET Core ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben:
Ereignisse
Power BI DataViz Weltmeisterschaften
14. Feb., 16 Uhr - 31. März, 16 Uhr
Mit 4 Chancen, ein Konferenzpaket zu gewinnen und es zum LIVE Grand Finale in Las Vegas zu machen
Weitere Informationen