Samouczek: rozpoczynanie pracy z EF Core aplikacją internetową MVC ASP.NET
Przez Tom Dykstra i Rick Anderson
W tym samouczku przedstawiono model ASP.NET Core MVC i program Entity Framework Core z kontrolerami i widokami. Strony Razor to alternatywny model programowania. W przypadku nowego projektu programowania zalecamy używanie stron Razor w zamiast modelu MVC z kontrolerami i widokami. Zobacz wersję tego samouczka dla stron Razor. Każdy z tych samouczków obejmuje pewne materiały, których nie ma w drugim:
Niektóre elementy tego samouczka modelu MVC, które nie są dostępne w przypadku stron Razor:
- Implementowanie dziedziczenia w modelu danych
- Wykonywanie pierwotnych zapytań SQL
- Używanie dynamicznych zapytań LINQ w celu uproszczenia kodu
Niektóre elementy samouczka dotyczącego stron Razor, których nie ma w tym samouczku:
- Ładowanie powiązanych danych za pomocą metody Select
- Najlepsze rozwiązania dotyczące platformy EF.
Przykładowa aplikacja internetowa Contoso University pokazuje, jak utworzyć aplikację internetową platformy ASP.NET Core MVC przy użyciu platformy Entity Framework (EF) Core i programu Visual Studio.
Przykładowa aplikacja to witryna internetowa fikcyjnego uniwersytetu Contoso. Obejmuje ona funkcje, takie jak wstęp dla uczniów, tworzenie kursów i zadania instruktora. Jest to pierwszy z serii samouczków, które wyjaśniają, jak utworzyć przykładową aplikację Contoso University.
Wymagania wstępne
- Jeśli dopiero zaczynasz ASP.NET Core MVC, zapoznaj się z serią samouczków Rozpoczynanie pracy z ASP.NET Core MVC przed rozpoczęciem tego samouczka.
- Program Visual Studio 2022 z pakietem roboczym tworzenia aplikacji ASP.NET i aplikacji internetowych.
- Zestaw SDK dla platformy .NET 6.0
Ten samouczek nie został zaktualizowany dla ASP.NET Core 6 lub nowszego. Instrukcje samouczka nie będą działać poprawnie, jeśli utworzysz projekt przeznaczony dla ASP.NET Core 6 lub nowszej wersji. Na przykład szablony sieci Web ASP.NET Core 6 i nowszych używają minimalnego modelu hostingu, który łączy Startup.cs
się i Program.cs
w jeden Program.cs
plik.
Kolejną różnicą wprowadzoną na platformie .NET 6 jest funkcja NRT (typy referencyjne dopuszczane do wartości null). Szablony projektów domyślnie włączają tę funkcję. Problemy mogą wystąpić, gdy program EF uważa, że właściwość musi być wymagana na platformie .NET 6, która jest dopuszczana do wartości null na platformie .NET 5. Na przykład strona Tworzenie ucznia zakończy się niepowodzeniem w trybie dyskretnym, chyba że Enrollments
właściwość ma wartość null lub asp-validation-summary
tag pomocnika zostanie zmieniony z ModelOnly
na All
.
Na potrzeby tego samouczka zalecamy zainstalowanie i użycie zestawu .NET 5 SDK. Dopóki ten samouczek nie zostanie zaktualizowany, zobacz Razor Strony z programem Entity Framework Core w programie ASP.NET Core — samouczek 1 z 8 , aby dowiedzieć się, jak używać platformy Entity Framework z programem ASP.NET Core 6 lub nowszym.
Aparaty bazy danych
Instrukcje programu Visual Studio używają programu SQL Server LocalDB — wersji programu SQL Server Express działającej tylko w systemie Windows.
Rozwiązywanie problemów i rozwiązywanie problemów
Jeśli napotkasz problem, którego nie możesz rozwiązać, zazwyczaj możesz znaleźć rozwiązanie, porównując kod z ukończonym projektem. Aby uzyskać listę typowych błędów i sposób ich rozwiązywania, zobacz sekcję Rozwiązywanie problemów z ostatnim samouczkiem z serii. Jeśli nie znajdziesz tam potrzebnych informacji, możesz opublikować pytanie, aby StackOverflow.com dla platformy ASP.NET Core lub EF Core.
Napiwek
Jest to seria 10 samouczków, z których każda opiera się na tym, co zostało wykonane we wcześniejszych samouczkach. Rozważ zapisanie kopii projektu po zakończeniu każdego pomyślnego ukończenia samouczka. Następnie, jeśli wystąpią problemy, możesz zacząć od poprzedniego samouczka zamiast wracać do początku całej serii.
Aplikacja internetowa Contoso University
Aplikacja wbudowana w te samouczki jest podstawową witryną internetową uniwersytetu.
Użytkownicy mogą wyświetlać i aktualizować informacje o uczniach, kursach i instruktorach. Oto kilka ekranów w aplikacji:
Tworzenie aplikacji internetowej
- Uruchom program Visual Studio i wybierz pozycję Utwórz nowy projekt.
- W oknie dialogowym Tworzenie nowego projektu wybierz pozycję ASP.NET Core Web Application>Next (Dalej).
- W oknie dialogowym Konfigurowanie nowego projektu wprowadź wartość
ContosoUniversity
w polu Nazwa projektu. Należy użyć tej dokładnej nazwy, w tym wielkich liter, więc każdynamespace
z nich jest zgodny podczas kopiowania kodu. - Wybierz pozycję Utwórz.
- W oknie dialogowym Tworzenie nowej aplikacji internetowej platformy ASP.NET Core wybierz pozycję:
- Platforma .NET Core i ASP.NET Core 5.0 na listach rozwijanych.
- ASP.NET Core Web App (Model-View-Controller).
- Utwórz
Konfigurowanie stylu witryny
Kilka podstawowych zmian umożliwia skonfigurowanie menu witryny, układu i home strony.
Otwórz Views/Shared/_Layout.cshtml
plik i wprowadź następujące zmiany:
- Zmień każde wystąpienie elementu
ContosoUniversity
naContoso University
. Istnieją trzy wystąpienia. - Dodaj pozycje menu Informacje, Uczniowie, Kursy, Instruktorzy i Działy oraz usuń Privacy wpis menu.
Powyższe zmiany są wyróżnione w następującym kodzie:
<!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>
W Views/Home/Index.cshtml
pliku zastąp zawartość pliku następującym znacznikiem:
@{
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>
Naciśnij CTRL+F5, aby uruchomić projekt, lub wybierz polecenie Debuguj > start bez debugowania z menu. Strona jest wyświetlana home z kartami stron utworzonych w tym samouczku.
EF Core Pakiety NuGet
W tym samouczku jest używany program SQL Server, a pakiet dostawcy to Microsoft.EntityFrameworkCore.SqlServer.
Pakiet EF SQL Server i jego zależności Microsoft.EntityFrameworkCore
oraz Microsoft.EntityFrameworkCore.Relational
, zapewniają obsługę środowiska uruchomieniowego dla platformy EF.
Dodaj pakiet NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore. W konsoli Menedżer pakietów (PMC) wprowadź następujące polecenia, aby dodać pakiety NuGet:
Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Pakiet NuGet udostępnia oprogramowanie pośredniczące ASP.NET Core dla EF Core stron błędów. To oprogramowanie pośredniczące pomaga wykrywać i diagnozować błędy związane z migracjami EF Core .
Aby uzyskać informacje o innych dostawcach baz danych dostępnych dla EF Coreprogramu , zobacz Dostawcy baz danych.
Tworzenie modelu danych
Dla tej aplikacji są tworzone następujące klasy jednostek:
Powyższe jednostki mają następujące relacje:
- Relacja jeden do wielu między jednostkami
Student
iEnrollment
. Student może być zarejestrowany w dowolnej liczbie kursów. - Relacja jeden do wielu między jednostkami
Course
iEnrollment
. Kurs może mieć dowolną liczbę uczniów zarejestrowanych w nim.
W poniższych sekcjach tworzona jest klasa dla każdej z tych jednostek.
Jednostka Student
W folderze Models utwórz klasę Student
przy użyciu następującego kodu:
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; }
}
}
Właściwość ID
jest kolumną klucza podstawowego (PK) tabeli bazy danych, która odpowiada tej klasie. Domyślnie program EF interpretuje właściwość o nazwie ID
lub classnameID
jako klucz podstawowy. Na przykład klucz PK może mieć nazwę StudentID
zamiast ID
.
Właściwość Enrollments
jest właściwością nawigacji. Właściwości nawigacji przechowują inne jednostki powiązane z tą jednostką. Enrollments
Właściwość Student
jednostki:
- Zawiera wszystkie
Enrollment
jednostki powiązane z jednostkąStudent
. - Jeśli określony
Student
wiersz w bazie danych ma dwa powiązaneEnrollment
wiersze:- Właściwość
Student
nawigacji tejEnrollments
jednostki zawiera te dwieEnrollment
jednostki.
- Właściwość
Enrollment
wiersze zawierają wartość PK ucznia w kolumnie klucza obcego StudentID
(FK).
Jeśli właściwość nawigacji może zawierać wiele jednostek:
- Typ musi być listą, taką jak
ICollection<T>
,List<T>
lubHashSet<T>
. - Jednostki można dodawać, usuwać i aktualizować.
Relacje nawigacji wiele do wielu i jeden do wielu mogą zawierać wiele jednostek. Gdy ICollection<T>
jest używany, program EF domyślnie tworzy HashSet<T>
kolekcję.
Jednostka Rejestracja
W folderze Models utwórz klasę Enrollment
przy użyciu następującego kodu:
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; }
}
}
Właściwość EnrollmentID
jest kluczem PK. Ta jednostka używa classnameID
wzorca zamiast ID
samego siebie. Jednostka użyła Student
ID
wzorca. Niektórzy deweloperzy wolą używać jednego wzorca w całym modelu danych. W tym samouczku odmiana ilustruje, że można użyć dowolnego wzorca. W późniejszym samouczku pokazano, jak użycie bez ID
nazwy klasy ułatwia implementowanie dziedziczenia w modelu danych.
Właściwość Grade
to enum
. Grade
Po ?
deklaracji typu wskazuje, że Grade
właściwość jest dopuszczana do wartości null. Ocena, która różni się null
od klasy zerowej. null
oznacza, że ocena nie jest znana lub nie została jeszcze przypisana.
Właściwość StudentID
jest kluczem obcym (FK), a odpowiadająca mu właściwość nawigacji to Student
. Jednostka Enrollment
jest skojarzona z jedną Student
jednostką, więc właściwość może przechowywać tylko jedną Student
jednostkę. Różni się to od Student.Enrollments
właściwości nawigacji, która może zawierać wiele Enrollment
jednostek.
Właściwość CourseID
jest kluczem FK, a odpowiadająca jej właściwość nawigacji to Course
. Jednostka Enrollment
jest skojarzona z jedną jednostką Course
.
Platforma Entity Framework interpretuje właściwość jako właściwość FK, jeśli ma nazwę właściwości nawigacji nazwa <
><
właściwości klucza>
podstawowego. Na przykład StudentID
dla Student
właściwości nawigacji, ponieważ Student
klucz PK jednostki to ID
. Właściwości klucza FK mogą być również nazwane <
nazwą>
właściwości klucza podstawowego. Na przykład ponieważ CourseID
klucz Course
PK jednostki to CourseID
.
Jednostka Course
W folderze Models utwórz klasę Course
przy użyciu następującego kodu:
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; }
}
}
Właściwość Enrollments
jest właściwością nawigacji. Jednostka Course
może być powiązana z dowolną Enrollment
liczbą jednostek.
Atrybut DatabaseGenerated został wyjaśniony w późniejszym samouczku. Ten atrybut umożliwia wprowadzenie klucza PK dla kursu zamiast generowania bazy danych.
Tworzenie kontekstu bazy danych
Główną klasą, która koordynuje funkcje ef dla danego modelu danych, jest DbContext klasa kontekstu bazy danych. Ta klasa jest tworzona przez wyprowadzanie z Microsoft.EntityFrameworkCore.DbContext
klasy . Klasa pochodna DbContext
określa, które jednostki są uwzględnione w modelu danych. Niektóre zachowania ef można dostosować. W tym projekcie klasa nosi nazwę SchoolContext
.
W folderze projektu utwórz folder o nazwie Data
.
W folderze Dane utwórz klasę SchoolContext
z następującym kodem:
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; }
}
}
Powyższy kod tworzy DbSet
właściwość dla każdego zestawu jednostek. W terminologii ef:
- Zestaw jednostek zwykle odpowiada tabeli bazy danych.
- Jednostka odpowiada wierszowi w tabeli.
Instrukcje DbSet<Enrollment>
i DbSet<Course>
mogą zostać pominięte i będą działać tak samo. Program EF uwzględnia je niejawnie, ponieważ:
- Jednostka
Student
odwołuje się doEnrollment
jednostki. - Jednostka
Enrollment
odwołuje się doCourse
jednostki.
Po utworzeniu bazy danych program EF tworzy tabele, które mają takie same nazwy jak DbSet
nazwy właściwości. Nazwy właściwości kolekcji są zwykle mnogią. Na przykład Students
zamiast Student
. Deweloperzy nie zgadzają się, czy nazwy tabel powinny być w liczbie mnogiej, czy nie. W przypadku tych samouczków domyślne zachowanie jest zastępowane przez określenie pojedynczych nazw tabel w pliku DbContext
. W tym celu dodaj następujący wyróżniony kod po ostatniej właściwości DbSet.
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");
}
}
}
Rejestrowanie SchoolContext
ASP.NET Core obejmuje wstrzykiwanie zależności. Usługi, takie jak kontekst bazy danych EF, są rejestrowane za pomocą wstrzykiwania zależności podczas uruchamiania aplikacji. Składniki, które wymagają tych usług, takich jak kontrolery MVC, są udostępniane za pośrednictwem parametrów konstruktora. Kod konstruktora kontrolera, który pobiera wystąpienie kontekstu, jest wyświetlany w dalszej części tego samouczka.
Aby zarejestrować się SchoolContext
jako usługa, otwórz plik Startup.cs
i dodaj wyróżnione wiersze do ConfigureServices
metody .
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();
}
Nazwa parametry połączenia jest przekazywana do kontekstu przez wywołanie metody w DbContextOptionsBuilder
obiekcie. W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje parametry połączenia z appsettings.json
pliku.
appsettings.json
Otwórz plik i dodaj parametry połączenia, jak pokazano w następującym znaczniku:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Dodawanie filtru wyjątku bazy danych
Dodaj AddDatabaseDeveloperPageExceptionFilter element do ConfigureServices
, jak pokazano w poniższym kodzie:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddControllersWithViews();
}
Zawiera AddDatabaseDeveloperPageExceptionFilter
przydatne informacje o błędach w środowisku deweloperów.
SQL Server Express LocalDB
Parametry połączenia określa sql Server LocalDB. LocalDB to uproszczona wersja aparatu bazy danych SQL Server Express i jest przeznaczona do tworzenia aplikacji, a nie do użytku produkcyjnego. Baza danych LocalDB uruchamia się na żądanie i działa w trybie użytkownika, więc nie ma złożonej konfiguracji. Domyślnie baza danych LocalDB tworzy pliki bazy danych .mdf w C:/Users/<user>
katalogu.
Inicjowanie bazy danych przy użyciu danych testowych
Program EF tworzy pustą bazę danych. W tej sekcji dodawana jest metoda wywoływana po utworzeniu bazy danych w celu wypełnienia jej danymi testowymi.
Metoda EnsureCreated
jest używana do automatycznego tworzenia bazy danych. W późniejszym samouczku zobaczysz, jak obsługiwać zmiany modelu przy użyciu Migracje Code First, aby zmienić schemat bazy danych zamiast usuwać i ponownie tworzyć bazę danych.
W folderze Dane utwórz nową klasę o nazwie przy użyciu DbInitializer
następującego kodu:
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();
}
}
}
Powyższy kod sprawdza, czy baza danych istnieje:
- Jeśli baza danych nie zostanie znaleziona;
- Jest on tworzony i ładowany z danymi testowymi. Ładuje dane testowe do tablic, a nie
List<T>
kolekcji w celu zoptymalizowania wydajności.
- Jest on tworzony i ładowany z danymi testowymi. Ładuje dane testowe do tablic, a nie
- Jeśli baza danych zostanie znaleziona, nie podejmuje żadnych działań.
Zaktualizuj Program.cs
za pomocą następującego kodu:
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
program wykonuje następujące czynności podczas uruchamiania aplikacji:
- Pobierz wystąpienie kontekstu bazy danych z kontenera wstrzykiwania zależności.
- Wywołaj metodę
DbInitializer.Initialize
. - Usuwanie kontekstu po zakończeniu
Initialize
metody, jak pokazano w poniższym kodzie:
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();
}
Przy pierwszym uruchomieniu aplikacji baza danych jest tworzona i ładowana z danymi testowymi. Za każdym razem, gdy model danych ulegnie zmianie:
- Usuń bazę danych.
- Zaktualizuj metodę inicjuj i rozpocznij od nowa przy użyciu nowej bazy danych.
W kolejnych samouczkach baza danych jest modyfikowana po zmianie modelu danych bez usuwania i ponownego tworzenia. W przypadku zmiany modelu danych żadne dane nie zostaną utracone.
Tworzenie kontrolera i widoków
Użyj aparatu tworzenia szkieletów w programie Visual Studio, aby dodać kontroler MVC i widoki, które będą używać programu EF do wykonywania zapytań i zapisywania danych.
Automatyczne tworzenie metod akcji CRUD i widoków jest nazywane tworzeniem szkieletów.
- W Eksplorator rozwiązań kliknij prawym przyciskiem
Controllers
myszy folder i wybierz polecenie Dodaj > nowy element szkieletowy. - W oknie dialogowym Dodawanie szkieletu:
- Wybierz kontroler MVC z widokami przy użyciu platformy Entity Framework.
- Kliknij przycisk Dodaj. Zostanie wyświetlone okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu programu Entity Framework :
- W klasie Model wybierz pozycję Student.
- W obszarze Klasa kontekstu danych wybierz pozycję SchoolContext.
- Zaakceptuj domyślną nazwę StudentsController .
- Kliknij przycisk Dodaj.
Aparat tworzenia szkieletów programu Visual Studio tworzy StudentsController.cs
plik i zestaw widoków (*.cshtml
plików), które współpracują z kontrolerem.
Zwróć uwagę, że kontroler przyjmuje SchoolContext
jako parametr konstruktora.
namespace ContosoUniversity.Controllers
{
public class StudentsController : Controller
{
private readonly SchoolContext _context;
public StudentsController(SchoolContext context)
{
_context = context;
}
ASP.NET Iniekcja zależności Core zajmuje się przekazywaniem wystąpienia SchoolContext
do kontrolera. Skonfigurowano to w Startup
klasie .
Kontroler zawiera metodę Index
akcji, która wyświetla wszystkich uczniów w bazie danych. Metoda pobiera listę uczniów z zestawu jednostek Students, odczytując Students
właściwość wystąpienia kontekstu bazy danych:
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
Elementy programowania asynchronicznego w tym kodzie zostały wyjaśnione w dalszej części tego samouczka.
Widok Views/Students/Index.cshtml
wyświetla tę listę w tabeli:
@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>
Naciśnij CTRL+F5, aby uruchomić projekt, lub wybierz polecenie Debuguj > start bez debugowania z menu.
Kliknij kartę Uczniowie, aby wyświetlić dane testowe wstawione przez metodę DbInitializer.Initialize
. W zależności od tego, jak wąskie jest okno przeglądarki, w górnej części strony zobaczysz Students
link tabulatora lub musisz kliknąć ikonę nawigacji w prawym górnym rogu, aby wyświetlić link.
Wyświetlanie bazy danych
Po uruchomieniu aplikacji metoda wywołuje metodę DbInitializer.Initialize
EnsureCreated
. Ef zobaczyła, że nie ma bazy danych:
- W związku z tym utworzono bazę danych.
- Kod
Initialize
metody wypełnił bazę danych danymi.
Użyj programu SQL Server Eksplorator obiektów (SSOX), aby wyświetlić bazę danych w programie Visual Studio:
- Wybierz pozycję SQL Server Eksplorator obiektów z menu Widok w programie Visual Studio.
- W programie SSOX wybierz pozycję (localdb)\MSSQLLocalDB > Databases.
- Wybierz
ContosoUniversity1
pozycję , wpis nazwy bazy danych, która znajduje się w parametry połączenia wappsettings.json
pliku. - Rozwiń węzeł Tabele, aby wyświetlić tabele w bazie danych.
Kliknij prawym przyciskiem myszy tabelę Student i kliknij pozycję Wyświetl dane , aby wyświetlić dane w tabeli.
Pliki *.mdf
i *.ldf
bazy danych znajdują się w folderze C:\Users\<username> .
Ponieważ EnsureCreated
jest wywoływana w metodzie inicjatora uruchamianej podczas uruchamiania aplikacji, możesz:
- Wprowadź zmianę w
Student
klasie. - Usuń bazę danych.
- Zatrzymaj, a następnie uruchom aplikację. Baza danych zostanie automatycznie utworzona ponownie, aby dopasować ją do zmiany.
Jeśli na przykład EmailAddress
właściwość zostanie dodana do Student
klasy, nowa EmailAddress
kolumna w ponownie utworzonej tabeli. Widok nie wyświetli nowej EmailAddress
właściwości.
Konwencje
Ilość kodu napisanego w celu utworzenia kompletnej bazy danych przez program EF jest minimalna ze względu na użycie konwencji ef:
- Nazwy
DbSet
właściwości są używane jako nazwy tabel. W przypadku jednostek, do których nie odwołuje sięDbSet
właściwość, nazwy klas jednostek są używane jako nazwy tabel. - Nazwy właściwości jednostki są używane dla nazw kolumn.
- Właściwości jednostki o nazwie
ID
lubclassnameID
są rozpoznawane jako właściwości PK. - Właściwość jest interpretowana jako właściwość FK, jeśli nazwa
<
właściwości nawigacji nazwa><
właściwości PK>
. Na przykładStudentID
dlaStudent
właściwości nawigacji, ponieważStudent
klucz PK jednostki toID
. Właściwości klucza FK mogą być również nazwane<
nazwą>
właściwości klucza podstawowego. Na przykład ponieważEnrollmentID
kluczEnrollment
PK jednostki toEnrollmentID
.
Konwencjonalne zachowanie można zastąpić. Na przykład nazwy tabel można jawnie określić, jak pokazano wcześniej w tym samouczku. Nazwy kolumn i dowolną właściwość można ustawić jako klucz PK lub FK.
Kod asynchroniczny
Programowanie asynchroniczne jest trybem domyślnym dla ASP.NET Core i EF Core.
Serwer internetowy ma ograniczoną liczbę dostępnych wątków, a w sytuacjach dużego obciążenia wszystkie dostępne wątki mogą być używane. W takim przypadku serwer nie może przetworzyć nowych żądań, dopóki wątki nie zostaną zwolnione. W przypadku kodu synchronicznego wiele wątków może być powiązanych, gdy nie wykonują żadnej pracy, ponieważ oczekują na zakończenie operacji we/wy. W przypadku kodu asynchronicznego, gdy proces oczekuje na ukończenie operacji we/wy, jego wątek zostanie zwolniony do użycia przez serwer do przetwarzania innych żądań. W związku z tym kod asynchroniczny umożliwia wydajniejsze wykorzystanie zasobów serwera, a serwer jest włączony do obsługi większej liczby ruchu bez opóźnień.
Kod asynchroniczny wprowadza niewielką ilość narzutów w czasie wykonywania, ale w przypadku małych sytuacji ruch trafień wydajności jest niewielki, podczas gdy w przypadku dużych sytuacji związanych z ruchem potencjalna poprawa wydajności jest znacząca.
W poniższym kodzie , async
, Task<T>
await
i ToListAsync
wykonaj kod asynchronicznie.
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
- Słowo
async
kluczowe nakazuje kompilatorowi generowanie wywołań zwrotnych dla części treści metody i automatyczne tworzenieTask<IActionResult>
zwracanego obiektu. - Zwracany typ
Task<IActionResult>
reprezentuje bieżącą pracę z wynikiem typuIActionResult
. - Słowo
await
kluczowe powoduje, że kompilator dzieli metodę na dwie części. Pierwsza część kończy się operacją, która została uruchomiona asynchronicznie. Druga część jest umieszczana w metodzie wywołania zwrotnego wywoływanej po zakończeniu operacji. ToListAsync
to asynchroniczna wersjaToList
metody rozszerzenia.
Niektóre kwestie, o których należy pamiętać podczas pisania kodu asynchronicznego korzystającego z programu EF:
- Tylko instrukcje, które powodują wysyłanie zapytań lub poleceń do bazy danych, są wykonywane asynchronicznie. Dotyczy to na przykład
ToListAsync
, iSingleOrDefaultAsync
SaveChangesAsync
. Nie zawiera na przykład instrukcji, które po prostu zmieniająIQueryable
element , na przykładvar students = context.Students.Where(s => s.LastName == "Davolio")
. - Kontekst EF nie jest bezpieczny wątkiem: nie próbuj wykonywać wielu operacji równolegle. Podczas wywoływania dowolnej metody asynchronicznej EF zawsze należy użyć słowa kluczowego
await
. - Aby skorzystać z zalet wydajności kodu asynchronicznego, upewnij się, że wszystkie pakiety bibliotek używane również używają asynchronicznego, jeśli wywołują jakiekolwiek metody EF, które powodują wysyłanie zapytań do bazy danych.
Aby uzyskać więcej informacji na temat programowania asynchronicznego na platformie .NET, zobacz Async Overview (Omówienie asynchroniczne).
Ogranicz pobrane jednostki
Zobacz Zagadnienia dotyczące wydajności, aby uzyskać informacje na temat ograniczania liczby jednostek zwracanych z zapytania.
Rejestrowanie SQL platformy Entity Framework Core
Konfiguracja rejestrowania jest często dostarczana za pomocą sekcji Logging
plików appsettings.{Environment}.json
. Aby zarejestrować instrukcje SQL, dodaj "Microsoft.EntityFrameworkCore.Database.Command": "Information"
do appsettings.Development.json
pliku:
{
"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": "*"
}
Po wcześniejszym kodzie JSON instrukcje SQL są wyświetlane w wierszu polecenia i w oknie danych wyjściowych programu Visual Studio.
Aby uzyskać więcej informacji, zobacz Rejestrowanie na platformie .NET Core i ASP.NET Core oraz ten problem z usługą GitHub.
Przejdź do następnego samouczka, aby dowiedzieć się, jak wykonywać podstawowe operacje CRUD (tworzenie, odczytywanie, aktualizowanie, usuwanie).
W tym samouczku przedstawiono model ASP.NET Core MVC i program Entity Framework Core z kontrolerami i widokami. Strony Razor to alternatywny model programowania. W przypadku nowego projektu programowania zalecamy używanie stron Razor w zamiast modelu MVC z kontrolerami i widokami. Zobacz wersję tego samouczka dla stron Razor. Każdy z tych samouczków obejmuje pewne materiały, których nie ma w drugim:
Niektóre elementy tego samouczka modelu MVC, które nie są dostępne w przypadku stron Razor:
- Implementowanie dziedziczenia w modelu danych
- Wykonywanie pierwotnych zapytań SQL
- Używanie dynamicznych zapytań LINQ w celu uproszczenia kodu
Niektóre elementy samouczka dotyczącego stron Razor, których nie ma w tym samouczku:
- Ładowanie powiązanych danych za pomocą metody Select
- Najlepsze rozwiązania dotyczące platformy EF.
Przykładowa aplikacja internetowa Contoso University pokazuje, jak tworzyć aplikacje internetowe platformy ASP.NET Core 2.2 MVC przy użyciu platformy Entity Framework (EF) Core 2.2 i programu Visual Studio 2019.
Ten samouczek nie został zaktualizowany dla ASP.NET Core 3.1. Została ona zaktualizowana dla ASP.NET Core 5.0.
Przykładowa aplikacja to witryna internetowa fikcyjnego uniwersytetu Contoso. Obejmuje ona funkcje, takie jak wstęp dla uczniów, tworzenie kursów i zadania instruktora. Jest to pierwszy z serii samouczków, które wyjaśniają, jak utworzyć przykładową aplikację Contoso University od podstaw.
Wymagania wstępne
- Zestaw .NET Core SDK 2.2
- Program Visual Studio 2019 z następującymi obciążeniami:
- obciążenie ASP.NET i tworzenie aplikacji internetowych
- Obciążenie programistyczne dla wielu platform .NET Core
Rozwiązywanie problemów
Jeśli napotkasz problem, którego nie możesz rozwiązać, zazwyczaj możesz znaleźć rozwiązanie, porównując kod z ukończonym projektem. Aby uzyskać listę typowych błędów i sposób ich rozwiązywania, zobacz sekcję Rozwiązywanie problemów z ostatnim samouczkiem z serii. Jeśli nie znajdziesz tam potrzebnych informacji, możesz opublikować pytanie, aby StackOverflow.com dla platformy ASP.NET Core lub EF Core.
Napiwek
Jest to seria 10 samouczków, z których każda opiera się na tym, co zostało wykonane we wcześniejszych samouczkach. Rozważ zapisanie kopii projektu po zakończeniu każdego pomyślnego ukończenia samouczka. Następnie, jeśli wystąpią problemy, możesz zacząć od poprzedniego samouczka zamiast wracać do początku całej serii.
Aplikacja internetowa Contoso University
Aplikacja, którą utworzysz w tych samouczkach, jest prostą witryną internetową uniwersytetu.
Użytkownicy mogą wyświetlać i aktualizować informacje o uczniach, kursach i instruktorach. Oto kilka ekranów, które utworzysz.
Tworzenie aplikacji internetowej
Otwórz program Visual Studio.
W menu Plik wybierz pozycję Nowy > projekt.
W okienku po lewej stronie wybierz pozycję Zainstalowano sieć > Web visual C#>.
Wybierz szablon projektu ASP.NET Core Web Application.
Wprowadź nazwę ContosoUniversity i kliknij przycisk OK.
Poczekaj na wyświetlenie okna dialogowego Nowa aplikacja internetowa ASP.NET Core.
Wybierz pozycję .NET Core, ASP.NET Core 2.2 i szablon Aplikacja internetowa (Model-View-Controller).
Upewnij się, że ustawienie Uwierzytelnianie ma wartość Brak uwierzytelniania.
Wybierz OK
Konfigurowanie stylu witryny
Kilka prostych zmian spowoduje skonfigurowanie menu witryny, układu i home strony.
Otwórz Views/Shared/_Layout.cshtml
plik i wprowadź następujące zmiany:
Zmień każde wystąpienie "ContosoUniversity" na "Contoso University". Istnieją trzy wystąpienia.
Dodaj pozycje menu Informacje, Uczniowie, Kursy, Instruktorzy i Działy oraz usuń Privacy wpis menu.
Zmiany są wyróżnione.
<!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>
W Views/Home/Index.cshtml
pliku zastąp zawartość pliku następującym kodem, aby zastąpić tekst ASP.NET i MVC tekstem o tej aplikacji:
@{
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>
Naciśnij CTRL+F5, aby uruchomić projekt, lub wybierz polecenie Debuguj > start bez debugowania z menu. Zostanie wyświetlona home strona z kartami stron, które zostaną utworzone w tych samouczkach.
Informacje o EF Core pakietach NuGet
Aby dodać EF Core obsługę projektu, zainstaluj dostawcę bazy danych, którego chcesz użyć. W tym samouczku jest używany program SQL Server, a pakiet dostawcy to Microsoft.EntityFrameworkCore.SqlServer. Ten pakiet jest zawarty w Microsoft.AspNetCore.App metapakiecie, więc nie trzeba odwoływać się do pakietu.
Pakiet EF SQL Server i jego zależności (Microsoft.EntityFrameworkCore
i Microsoft.EntityFrameworkCore.Relational
) zapewniają obsługę środowiska uruchomieniowego dla programu EF. Później dodasz pakiet narzędzi w samouczku Migracje .
Aby uzyskać informacje o innych dostawcach baz danych dostępnych dla platformy Entity Framework Core, zobacz Dostawcy baz danych.
Tworzenie modelu danych
Następnie utworzysz klasy jednostek dla aplikacji Contoso University. Zaczniesz od następujących trzech jednostek.
Istnieje relacja jeden do wielu między jednostkami Student
i Enrollment
, a istnieje relacja jeden do wielu między jednostkami Course
i Enrollment
. Innymi słowy, student może być zarejestrowany w dowolnej liczbie kursów, a kurs może mieć dowolną liczbę uczniów zarejestrowanych w nim.
W poniższych sekcjach utworzysz klasę dla każdej z tych jednostek.
Jednostka Student
W folderze Models utwórz plik klasy o nazwie Student.cs
i zastąp kod szablonu następującym kodem.
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; }
}
}
Właściwość ID
stanie się kolumną klucza podstawowego tabeli bazy danych, która odpowiada tej klasie. Domyślnie platforma Entity Framework interpretuje właściwość o nazwie ID
lub classnameID
jako klucz podstawowy.
Właściwość Enrollments
jest właściwością nawigacji. Właściwości nawigacji przechowują inne jednostki powiązane z tą jednostką. W takim przypadku Enrollments
właściwość Student entity
obiektu będzie przechowywać wszystkie Enrollment
jednostki powiązane z tą Student
jednostką. Innymi słowy, jeśli Student
wiersz w bazie danych zawiera dwa powiązane Enrollment
wiersze (wiersze zawierające podstawową wartość klucza ucznia w kolumnie klucza obcego StudentID), Student
właściwość nawigacji tej jednostki Enrollments
będzie zawierać te dwie Enrollment
jednostki.
Jeśli właściwość nawigacji może zawierać wiele jednostek (jak w relacjach wiele do wielu lub jeden do wielu), jej typ musi być listą, w której można dodawać, usuwać i aktualizować wpisy, takie jak ICollection<T>
. Można określić ICollection<T>
lub typ, taki jak List<T>
lub HashSet<T>
. Jeśli określisz ICollection<T>
wartość , program EF domyślnie tworzy HashSet<T>
kolekcję.
Jednostka Rejestracja
W folderze Models utwórz Enrollment.cs
i zastąp istniejący kod następującym kodem:
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; }
}
}
Właściwość będzie kluczem podstawowym. Ta EnrollmentID
jednostka używa classnameID
wzorca zamiast ID
samego siebie, jak pokazano w jednostce Student
. Zazwyczaj należy wybrać jeden wzorzec i używać go w całym modelu danych. W tym miejscu odmiana ilustruje, że można użyć dowolnego wzorca. W późniejszym samouczku zobaczysz, jak używanie identyfikatora bez nazwy klasy ułatwia implementowanie dziedziczenia w modelu danych.
Właściwość Grade
to enum
. Znak zapytania po Grade
deklaracji typu wskazuje, że Grade
właściwość jest dopuszczana do wartości null. Klasa, która ma wartość null, różni się od klasy zerowej — wartość null oznacza, że ocena nie jest znana lub nie została jeszcze przypisana.
Właściwość StudentID
jest kluczem obcym, a odpowiadająca mu właściwość nawigacji to Student
. Jednostka Enrollment
jest skojarzona z jedną Student
jednostką, więc właściwość może przechowywać tylko jedną Student
jednostkę (w przeciwieństwie do Student.Enrollments
właściwości nawigacji, która może zawierać wiele Enrollment
jednostek).
Właściwość CourseID
jest kluczem obcym, a odpowiadająca mu właściwość nawigacji to Course
. Jednostka Enrollment
jest skojarzona z jedną jednostką Course
.
Program Entity Framework interpretuje właściwość jako właściwość klucza obcego, jeśli jest ona nazwana <navigation property name><primary key property name>
(na przykład dla Student
właściwości nawigacji, StudentID
ponieważ Student
klucz podstawowy jednostki to ID
). Właściwości klucza obcego można również nazwać po prostu <primary key property name>
(na przykład CourseID
ponieważ Course
klucz podstawowy jednostki to CourseID
).
Jednostka Course
W folderze Models utwórz Course.cs
i zastąp istniejący kod następującym kodem:
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; }
}
}
Właściwość Enrollments
jest właściwością nawigacji. Jednostka Course
może być powiązana z dowolną Enrollment
liczbą jednostek.
Więcej informacji na temat atrybutu DatabaseGenerated
znajdziesz w dalszej części tego samouczka w tej serii. Zasadniczo ten atrybut umożliwia wprowadzenie klucza podstawowego dla kursu zamiast generowania bazy danych.
Tworzenie kontekstu bazy danych
Główną klasą, która koordynuje funkcje programu Entity Framework dla danego modelu danych, jest klasa kontekstu bazy danych. Ta klasa jest tworzona przez wyprowadzenie z Microsoft.EntityFrameworkCore.DbContext
klasy . W kodzie określisz, które jednostki są uwzględnione w modelu danych. Można również dostosować pewne zachowanie platformy Entity Framework. W tym projekcie klasa nosi nazwę SchoolContext
.
W folderze projektu utwórz folder o nazwie Dane.
W folderze Dane utwórz nowy plik klasy o nazwie SchoolContext.cs
i zastąp kod szablonu następującym kodem:
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; }
}
}
Ten kod tworzy DbSet
właściwość dla każdego zestawu jednostek. W terminologii platformy Entity Framework zestaw jednostek zwykle odpowiada tabeli bazy danych, a jednostka odpowiada wierszowi w tabeli.
Można pominąć instrukcje DbSet<Enrollment>
i DbSet<Course>
i działałoby to samo. Program Entity Framework uwzględnia je niejawnie, ponieważ Student
jednostka odwołuje się do Enrollment
jednostki, a Enrollment
jednostka odwołuje się do Course
jednostki.
Po utworzeniu bazy danych program EF tworzy tabele, które mają takie same nazwy jak DbSet
nazwy właściwości. Nazwy właściwości kolekcji są zwykle mnogią (Uczniowie, a nie Student), ale deweloperzy nie zgadzają się, czy nazwy tabel powinny być w liczbie mnogiej, czy nie. W tych samouczkach zastąpisz domyślne zachowanie, określając pojedyncze nazwy tabel w obiekcie DbContext. W tym celu dodaj następujący wyróżniony kod po ostatniej właściwości DbSet.
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");
}
}
}
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Rejestrowanie elementu SchoolContext
ASP.NET Core domyślnie implementuje wstrzykiwanie zależności. Usługi (takie jak kontekst bazy danych EF) są rejestrowane za pomocą wstrzykiwania zależności podczas uruchamiania aplikacji. Składniki, które wymagają tych usług (takich jak kontrolery MVC), są udostępniane za pośrednictwem parametrów konstruktora. W dalszej części tego samouczka zobaczysz kod konstruktora kontrolera, który pobiera wystąpienie kontekstu.
Aby zarejestrować się SchoolContext
jako usługa, otwórz plik Startup.cs
i dodaj wyróżnione wiersze do ConfigureServices
metody .
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();
}
Nazwa parametry połączenia jest przekazywana do kontekstu przez wywołanie metody w DbContextOptionsBuilder
obiekcie. W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje parametry połączenia z appsettings.json
pliku.
Dodaj using
instrukcje dla ContosoUniversity.Data
przestrzeni nazw i Microsoft.EntityFrameworkCore
, a następnie skompiluj projekt.
using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;
appsettings.json
Otwórz plik i dodaj parametry połączenia, jak pokazano w poniższym przykładzie.
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
SQL Server Express LocalDB
Parametry połączenia określa bazę danych SQL Server LocalDB. LocalDB to uproszczona wersja aparatu bazy danych SQL Server Express i jest przeznaczona do tworzenia aplikacji, a nie do użytku produkcyjnego. Baza danych LocalDB uruchamia się na żądanie i działa w trybie użytkownika, więc nie ma złożonej konfiguracji. Domyślnie baza danych LocalDB tworzy pliki bazy danych .mdf w C:/Users/<user>
katalogu.
Inicjowanie bazy danych przy użyciu danych testowych
Platforma Entity Framework utworzy pustą bazę danych. W tej sekcji napiszesz metodę wywoływaną po utworzeniu bazy danych, aby wypełnić ją danymi testowymi.
W tym miejscu użyjesz EnsureCreated
metody , aby automatycznie utworzyć bazę danych. W późniejszym samouczku dowiesz się, jak obsługiwać zmiany modelu przy użyciu Migracje Code First, aby zmienić schemat bazy danych zamiast usuwać i ponownie tworzyć bazę danych.
W folderze Dane utwórz nowy plik klasy o nazwie DbInitializer.cs
i zastąp kod szablonu następującym kodem, co powoduje utworzenie bazy danych w razie potrzeby i załadowanie danych testowych do nowej bazy danych.
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();
}
}
}
Kod sprawdza, czy w bazie danych znajdują się jakieś uczniowie, a jeśli nie, zakłada, że baza danych jest nowa i musi zostać rozstawiona z danymi testowymi. Ładuje dane testowe do tablic, a nie List<T>
kolekcji w celu zoptymalizowania wydajności.
W Program.cs
pliku zmodyfikuj metodę , Main
aby wykonać następujące czynności podczas uruchamiania aplikacji:
- Pobierz wystąpienie kontekstu bazy danych z kontenera wstrzykiwania zależności.
- Wywołaj metodę seed, przekazując do niej kontekst.
- Po zakończeniu metody inicjowania należy usunąć kontekst.
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>();
});
}
}
Przy pierwszym uruchomieniu aplikacji baza danych zostanie utworzona i rozstawiona z danymi testowymi. Za każdym razem, gdy zmienisz model danych:
- Usuń bazę danych.
- Zaktualizuj metodę inicjuj i rozpocznij od nowa nową bazę danych w taki sam sposób.
W kolejnych samouczkach dowiesz się, jak zmodyfikować bazę danych, gdy model danych ulegnie zmianie, bez usuwania i ponownego tworzenia bazy danych.
Tworzenie kontrolera i widoków
W tej sekcji aparat tworzenia szkieletów w programie Visual Studio służy do dodawania kontrolera MVC i widoków, które będą używać programu EF do wykonywania zapytań i zapisywania danych.
Automatyczne tworzenie metod akcji CRUD i widoków jest nazywane tworzeniem szkieletów. Tworzenie szkieletów różni się od generowania kodu w tym, że szkielet kodu jest punktem wyjścia, który można zmodyfikować zgodnie z własnymi wymaganiami, podczas gdy zwykle nie modyfikuje się wygenerowanego kodu. Gdy konieczne jest dostosowanie wygenerowanego kodu, należy użyć klas częściowych lub ponownie wygenerować kod po zmianie.
- Kliknij prawym przyciskiem myszy folder Controllers w Eksplorator rozwiązań i wybierz polecenie Dodaj > nowy element szkieletowy.
- W oknie dialogowym Dodawanie szkieletu:
- Wybierz kontroler MVC z widokami przy użyciu platformy Entity Framework.
- Kliknij przycisk Dodaj. Zostanie wyświetlone okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu programu Entity Framework :
- W obszarze Klasa modelu wybierz pozycję Student.
- W obszarze Klasa kontekstu danych wybierz pozycję SchoolContext.
- Zaakceptuj domyślną nazwę StudentsController .
- Kliknij przycisk Dodaj.
Aparat tworzenia szkieletów programu Visual Studio tworzy StudentsController.cs
plik i zestaw widoków (.cshtml
plików), które współpracują z kontrolerem.
Zwróć uwagę, że kontroler przyjmuje SchoolContext
jako parametr konstruktora.
namespace ContosoUniversity.Controllers
{
public class StudentsController : Controller
{
private readonly SchoolContext _context;
public StudentsController(SchoolContext context)
{
_context = context;
}
ASP.NET Iniekcja zależności Core zajmuje się przekazywaniem wystąpienia SchoolContext
do kontrolera. To zostało skonfigurowane w Startup.cs
pliku.
Kontroler zawiera metodę Index
akcji, która wyświetla wszystkich uczniów w bazie danych. Metoda pobiera listę uczniów z zestawu jednostek Students, odczytując Students
właściwość wystąpienia kontekstu bazy danych:
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
W dalszej części tego samouczka poznasz elementy programowania asynchronicznego.
Widok Views/Students/Index.cshtml
wyświetla tę listę w tabeli:
@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>
Naciśnij CTRL+F5, aby uruchomić projekt, lub wybierz polecenie Debuguj > start bez debugowania z menu.
Kliknij kartę Uczniowie, aby wyświetlić dane testowe wstawione przez metodę DbInitializer.Initialize
. W zależności od tego, jak wąskie jest okno przeglądarki, w górnej części strony zobaczysz Students
link tabulatora lub musisz kliknąć ikonę nawigacji w prawym górnym rogu, aby wyświetlić link.
Wyświetlanie bazy danych
Po uruchomieniu aplikacji metoda wywołuje metodę DbInitializer.Initialize
EnsureCreated
. Program EF widział, że nie ma bazy danych i dlatego utworzył ją, a następnie pozostałą część Initialize
kodu metody wypełniła bazę danych danymi. Aby wyświetlić bazę danych w programie Visual Studio, możesz użyć programu SQL Server Eksplorator obiektów (SSOX).
Zamknij okno przeglądarki.
Jeśli okno SSOX nie jest jeszcze otwarte, wybierz je z menu Widok w programie Visual Studio.
W programie SSOX kliknij pozycję (localdb)\MSSQLLocalDB > Databases, a następnie kliknij wpis nazwy bazy danych, która znajduje się w parametry połączenia w appsettings.json
pliku.
Rozwiń węzeł Tabele, aby wyświetlić tabele w bazie danych.
Kliknij prawym przyciskiem myszy tabelę Student i kliknij pozycję Wyświetl dane , aby wyświetlić utworzone kolumny i wiersze wstawione do tabeli.
Pliki bazy danych .mdf i ldf znajdują się w folderze C:\Users\<username> .
Ponieważ wywołujesz EnsureCreated
metodę inicjatora uruchamianą podczas uruchamiania aplikacji, możesz teraz wprowadzić zmianę Student
w klasie, usunąć bazę danych, ponownie uruchomić aplikację, a baza danych zostanie automatycznie utworzona ponownie, aby dopasować ją do zmiany. Jeśli na przykład dodasz EmailAddress
właściwość do Student
klasy, zobaczysz nową EmailAddress
kolumnę w ponownie utworzonej tabeli.
Konwencje
Ilość kodu, który trzeba było napisać, aby program Entity Framework mógł utworzyć pełną bazę danych, jest minimalny ze względu na użycie konwencji lub założeń, które wykonuje program Entity Framework.
- Nazwy
DbSet
właściwości są używane jako nazwy tabel. W przypadku jednostek, do których nie odwołuje sięDbSet
właściwość, nazwy klas jednostek są używane jako nazwy tabel. - Nazwy właściwości jednostki są używane dla nazw kolumn.
- Właściwości jednostki o nazwie ID lub classnameID są rozpoznawane jako właściwości klucza podstawowego.
- Właściwość jest interpretowana jako właściwość klucza obcego, jeśli nosi nazwę właściwości nawigacji nazwa><właściwości klucza podstawowego (na przykład dla
Student
właściwości nawigacji,StudentID
ponieważStudent
klucz podstawowy> jednostki toID
).< Właściwości klucza obcego można również nazwać po prostu <nazwą> właściwości klucza podstawowego (na przykład ponieważEnrollmentID
Enrollment
klucz podstawowy jednostki to ).EnrollmentID
Konwencjonalne zachowanie można zastąpić. Można na przykład jawnie określić nazwy tabel, jak pokazano wcześniej w tym samouczku. Możesz również ustawić nazwy kolumn i ustawić dowolną właściwość jako klucz podstawowy lub klucz obcy, jak pokazano w dalszej części tego samouczka .
Kod asynchroniczny
Programowanie asynchroniczne jest trybem domyślnym dla ASP.NET Core i EF Core.
Serwer internetowy ma ograniczoną liczbę dostępnych wątków, a w sytuacjach dużego obciążenia wszystkie dostępne wątki mogą być używane. W takim przypadku serwer nie może przetworzyć nowych żądań, dopóki wątki nie zostaną zwolnione. W przypadku kodu synchronicznego wiele wątków może być powiązanych, gdy nie wykonują żadnej pracy, ponieważ oczekują na zakończenie operacji we/wy. W przypadku kodu asynchronicznego, gdy proces oczekuje na ukończenie operacji we/wy, jego wątek zostanie zwolniony do użycia przez serwer do przetwarzania innych żądań. W związku z tym kod asynchroniczny umożliwia wydajniejsze wykorzystanie zasobów serwera, a serwer jest włączony do obsługi większej liczby ruchu bez opóźnień.
Kod asynchroniczny wprowadza niewielką ilość narzutów w czasie wykonywania, ale w przypadku małych sytuacji ruch trafień wydajności jest niewielki, podczas gdy w przypadku dużych sytuacji związanych z ruchem potencjalna poprawa wydajności jest znacząca.
W poniższym kodzie słowo kluczowe, wartość zwracana, Task<T>
await
słowo kluczowe i ToListAsync
metoda sprawiają, async
że kod jest wykonywany asynchronicznie.
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
- Słowo
async
kluczowe nakazuje kompilatorowi generowanie wywołań zwrotnych dla części treści metody i automatyczne tworzenieTask<IActionResult>
zwracanego obiektu. - Zwracany typ
Task<IActionResult>
reprezentuje bieżącą pracę z wynikiem typuIActionResult
. - Słowo
await
kluczowe powoduje, że kompilator dzieli metodę na dwie części. Pierwsza część kończy się operacją, która została uruchomiona asynchronicznie. Druga część jest umieszczana w metodzie wywołania zwrotnego wywoływanej po zakończeniu operacji. ToListAsync
to asynchroniczna wersjaToList
metody rozszerzenia.
Niektóre kwestie, o których należy pamiętać podczas pisania kodu asynchronicznego korzystającego z programu Entity Framework:
- Tylko instrukcje, które powodują wysyłanie zapytań lub poleceń do bazy danych, są wykonywane asynchronicznie. Dotyczy to na przykład
ToListAsync
, iSingleOrDefaultAsync
SaveChangesAsync
. Nie zawiera na przykład instrukcji, które po prostu zmieniająIQueryable
element , na przykładvar students = context.Students.Where(s => s.LastName == "Davolio")
. - Kontekst EF nie jest bezpieczny wątkiem: nie próbuj wykonywać wielu operacji równolegle. Podczas wywoływania dowolnej metody asynchronicznej EF zawsze należy użyć słowa kluczowego
await
. - Jeśli chcesz skorzystać z zalet wydajności kodu asynchronicznego, upewnij się, że wszystkie używane pakiety bibliotek (takie jak na potrzeby stronicowania), należy również użyć asynchronicznego, jeśli wywołują one dowolne metody programu Entity Framework, które powodują wysyłanie zapytań do bazy danych.
Aby uzyskać więcej informacji na temat programowania asynchronicznego na platformie .NET, zobacz Async Overview (Omówienie asynchroniczne).
Następne kroki
Przejdź do następnego samouczka, aby dowiedzieć się, jak wykonywać podstawowe operacje CRUD (tworzenie, odczytywanie, aktualizowanie, usuwanie).