Razor Stránky s Entity Framework Core v ASP.NET Core – kurz 1 z 8

Note

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

Warning

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

Tom Dykstra, Jeremy Likness a Jon P Smith

Toto je první v řadě kurzů, které ukazují, jak používat Entity Framework (EF) Core v aplikaci ASP.NET Core Razor Pages . Tyto kurzy slouží k vytvoření webu pro fiktivní univerzitu Contoso. Web obsahuje funkce, jako je přijetí studentů, vytvoření kurzu a zadání instruktora. Tento kurz využívá přístup code-first. Informace o sledování tohoto kurzu s využitím prvního přístupu k databázi najdete v tomto problému na GitHubu.

Stáhněte nebo zobrazte dokončenou aplikaci.Pokyny ke stažení

Prerequisites

  • Pokud se Razor stránkami teprve začínáte, projděte si před zahájením tohoto kurzu sérii kurzů Začínáme s Razor Pages.

Databázové stroje

Pokyny pro Visual Studio používají SQL Server LocalDB, verzi SQL Serveru Express, která běží jenom ve Windows.

Troubleshooting

Pokud narazíte na problém, který nemůžete vyřešit, porovnejte kód s dokončeným projektem. Dobrý způsob, jak získat pomoc, je odesláním otázky na StackOverflow.com pomocí značky ASP.NET Core nebo značkyEF Core.

Ukázková aplikace

Aplikace vytvořená v těchto kurzech je základní web pro vysokoškoláky. Uživatelé můžou zobrazit a aktualizovat informace o studentech, kurzech a instruktorech. Zde je několik obrazovek vytvořených v tomto kurzu.

Indexová stránka studentů

Stránka pro úpravu studentů

Styl uživatelského rozhraní tohoto webu je založený na předdefinovaných šablonách projektů. Tento kurz se zaměřuje na použití EF Core s ASP.NET Core, nikoli na přizpůsobení uživatelského rozhraní.

Volitelné: Sestavení ukázkového stažení

Tento krok je nepovinný. Sestavení dokončené aplikace se doporučuje, když máte problémy, které nemůžete vyřešit. Pokud narazíte na problém, který nemůžete vyřešit, porovnejte kód s dokončeným projektem. Pokyny ke stažení

Výběrem ContosoUniversity.csproj otevřete projekt.

  • Zkompilujte projekt.

  • V konzole Správce balíčků (PMC) spusťte následující příkaz:

    Update-Database
    

Spusťte projekt, aby se databáze naplnila počátečními daty.

Vytvoření projektu webové aplikace

  1. Spusťte Visual Studio 2022 a vyberte Vytvořit nový projekt.

    Vytvoření nového projektu z úvodního okna

  2. V dialogovém okně Vytvořit nový projekt vyberte ASP.NET Core Web App a pak vyberte Další.

    Vytvoření webové aplikace ASP.NET Core

  3. V dialogovém okně Konfigurovat nový projekt zadejte ContosoUniversity název projektu. Je důležité pojmenovat projekt ContosoUniversity, včetně porovnávání velkých písmen, aby se obory názvů při kopírování a vkládání ukázkového kódu shodovaly.

  4. Vyberte Další.

  5. V dialogovém okně Další informace vyberte .NET 6.0 (dlouhodobá podpora) a pak vyberte Vytvořit.

    Další informace

Nastavení stylu webu

Zkopírujte a vložte do Pages/Shared/_Layout.cshtml souboru následující kód:

<!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" asp-append-version="true" />
    <link rel="stylesheet" href="~/ContosoUniversity.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">Contoso University</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-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-page="/About">About</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">Students</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Courses/Index">Courses</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Instructors/Index">Instructors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Departments/Index">Departments</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

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

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

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

Soubor rozvržení určuje záhlaví, zápatí a menu webu. Předchozí kód provede následující změny:

  • Každý výskyt "ContosoUniversity" změňte na "Contoso University". Existují tři výskyty.
  • Položky nabídky Home a Privacy byly odstraněny.
  • Položky jsou přidány pro About, Students, Courses, Instructors a Departments.

Nahraďte Pages/Index.cshtmlobsah souboru následujícím kódem:

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

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

Předchozí kód nahradí text o ASP.NET Core textem o této aplikaci.

Spuštěním aplikace ověřte, že se zobrazí domovská stránka.

Datový model

Následující části vytvoří datový model:

Diagram datového modelu course-enrollment-student

Student se může zaregistrovat do libovolného počtu kurzů a kurz může mít v něm zaregistrovaný libovolný počet studentů.

Entita Studenta

Diagram entit studentů

  • Ve složce projektu vytvořte složku Models .
  • Vytvořte Models/Student.cs pomocí následujícího kódu:
    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; }
        }
    }
    

Vlastnost ID se stane sloupcem primárního klíče v tabulce databáze, která odpovídá této třídě. Ve výchozím nastavení EF Core interpretuje vlastnost s názvem ID nebo classnameID jako primární klíč. Takže automaticky rozpoznaný alternativní název primárního klíče třídy Student je StudentID. Další informace najdete v tématu EF Core – Klíče.

Vlastnost Enrollments je navigační vlastnost. Vlastnosti navigace obsahují další entity, které souvisejí s touto entitou. V tomto případě Enrollments vlastnost Student entity obsahuje všechny Enrollment entity, které se vztahují k tomuto studentu. Pokud má například řádek Student v databázi dva související řádky registrace, Enrollments navigační vlastnost obsahuje tyto dvě entity registrace.

V databázi se řádek Registrace vztahuje k řádku Student, pokud jeho StudentID sloupec obsahuje hodnotu ID studenta. Předpokládejme například, že řádek Student má ID=1. Související řádky registrace budou mít StudentID hodnotu = 1. StudentID je cizí klíč v tabulce Registrace.

Vlastnost Enrollments je definována jako ICollection<Enrollment>, protože může existovat více souvisejících entit registrace. Lze použít jiné typy kolekcí, například List<Enrollment> .HashSet<Enrollment> Když se použije ICollection<Enrollment>, EF Core ve výchozím nastavení vytvoří kolekci HashSet<Enrollment>.

entita registrace

Diagram entity registrace

Vytvořte Models/Enrollment.cs pomocí následujícího kódu:

using System.ComponentModel.DataAnnotations;

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; }
        [DisplayFormat(NullDisplayText = "No grade")]
        public Grade? Grade { get; set; }

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

Vlastnost EnrollmentID je primární klíč; tato entita používá vzor classnameID namísto samotného ID. V případě produkčního datového modelu si mnoho vývojářů zvolí jeden vzor a konzistentně ho použije. V tomto kurzu se obě používají k ilustraci toho, že obě fungují. Použití ID bez classname usnadnění implementace některých druhů změn datového modelu.

Vlastnost Grade je enum. Otazník za deklarací typu Grade značí, že vlastnost Grade může mít hodnotu null. Známka, která má hodnotu null, se liší od nulové známky – hodnota null znamená, že známka není známa nebo ještě nebyla přiřazena.

Vlastnost StudentID je cizí klíč a odpovídající navigační vlastnost je Student. Entita Enrollment je přidružená k jedné Student entitě, takže vlastnost obsahuje jednu Student entitu.

Vlastnost CourseID je cizí klíč a odpovídající navigační vlastnost je Course. Entita Enrollment je přidružená k jedné Course entitě.

EF Core interpretuje vlastnost jako cizí klíč, pokud je pojmenovaná <navigation property name><primary key property name>. NapříkladStudentID je cizím klíčem pro navigační vlastnost Student, protože primárním klíčem entity Student je ID. Vlastnosti cizího klíče lze také pojmenovat <primary key property name>. Například, CourseID protože primární klíč entity Course je CourseID.

Entita Course

Diagram entit kurzu

Vytvořte Models/Course.cs pomocí následujícího kódu:

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

Vlastnost Enrollments je navigační vlastnost. Entita Course může souviset s libovolným počtem Enrollment entit.

Atribut DatabaseGenerated umožňuje aplikaci místo vygenerování databáze zadat primární klíč.

Sestavení aplikace Kompilátor vygeneruje několik upozornění na způsob null zpracování hodnot. Další informace najdete v tomto problému na GitHubu, referenčních typech s možnou hodnotou null a Kurzu: Vyjádřete záměr návrhu jasněji pomocí referenčních typů s možnou hodnotou null a bez možnosti null.

Chcete-li odstranit upozornění na odkazové typy s možnou hodnotou null, odeberte ze souboru ContosoUniversity.csproj následující řádek:

<Nullable>enable</Nullable>

Modul scaffolding v současné době nepodporuje odkazové typy s povolenou hodnotou null, a proto je nemohou používat ani modely použité při generování.

Odeberte anotaci odkazového typu s možnou hodnotou null ? z public string? RequestId { get; set; } v Pages/Error.cshtml.cs, aby se projekt sestavil bez upozornění kompilátoru.

Vytvořit stránky studentů

V této části se k vygenerování používá nástroj scaffolding pro ASP.NET Core:

  • Třída EF CoreDbContext. Kontext je hlavní třída, která koordinuje funkce Entity Framework pro daný datový model. Odvozuje se z třídy Microsoft.EntityFrameworkCore.DbContext.
  • Razor stránky, které zpracovávají operace vytvoření, čtení, aktualizace a odstranění (CRUD) pro entitu Student .
  • Vytvořte složku Pages/Students .
  • V Průzkumníku řešení klikněte pravým tlačítkem na složku Pages/Students a vyberte Přidat>Nová generovaná položka.
  • V dialogovém okně Přidat novou položku generátoru:
    • Na kartě vlevo vyberte Nainstalované > společné >Razor stránky
    • Vyberte Razor Stránky pomocí Entity Framework (CRUD)>ADD.
  • V dialogovém okně Přidat Razor stránky pomocí entity Framework (CRUD):
    • V rozevíracím seznamu Třída modelu vyberte Student (ContosoUniversity.Models).
    • V řádku Data context class vyberte symbol + (plus).
      • Změňte název kontextu dat tak, aby končil SchoolContext místo ContosoUniversityContext. Aktualizovaný název kontextu: ContosoUniversity.Data.SchoolContext
      • Výběrem možnosti Přidat dokončíte přidání třídy kontextu dat.
      • Výběrem možnosti Přidat dokončete dialogové okno Přidat Razor stránky .

Automaticky se nainstalují následující balíčky:

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

Pokud předchozí krok selže, sestavte projekt a opakujte krok generování.

Proces scaffoldingu:

  • Vytvoří Razor stránky ve složce Pages/Students :
    • Create.cshtml a Create.cshtml.cs
    • Delete.cshtml a Delete.cshtml.cs
    • Details.cshtml a Details.cshtml.cs
    • Edit.cshtml a Edit.cshtml.cs
    • Index.cshtml a Index.cshtml.cs
  • Vytvoří Data/SchoolContext.cs.
  • Přidá kontext do injektáže závislostí v Program.cssouboru .
  • Přidá připojovací řetězec databáze do appsettings.json.

Připojovací řetězec databáze

Nástroj pro generování pomocného kódu vygeneruje v souboru appsettings.json připojovací řetězec.

Připojovací řetězec určuje SQL Server LocalDB:

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

LocalDB je zjednodušená verze databázového stroje SQL Server Express a je určená pro vývoj aplikací, nikoli pro produkční použití. Ve výchozím nastavení LocalDB vytvoří .mdf soubory v C:/Users/<user> adresáři.

Aktualizace třídy kontextu databáze

Hlavní třída, která koordinuje EF Core funkce pro daný datový model, je třída kontextu databáze. Kontext je odvozen z Microsoft.EntityFrameworkCore.DbContext. Kontext určuje, které entity jsou součástí datového modelu. V tomto projektu má třída název SchoolContext.

Aktualizujte Data/SchoolContext.cs následujícím kódem:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

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

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

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

Předchozí kód se změní z jednotného čísla DbSet<Student> Student na množné číslo DbSet<Student> Students. Pokud chcete, aby Razor kód Stránky odpovídal novému DBSet názvu, proveďte globální změnu z: _context.Student. k: _context.Students.

Existuje 8 výskytů.

Vzhledem k tomu, že sada entit obsahuje více entit, mnoho vývojářů dává přednost DBSet názvům vlastností v množném čísle.

Zvýrazněný kód:

  • Vytvoří DbSet<TEntity> vlastnost pro každou sadu entit. V terminologii EF Core:
    • Sada entit obvykle odpovídá databázové tabulce.
    • Entita odpovídá řádku v tabulce.
  • Zavolá metodu OnModelCreating. OnModelCreating:
    • Volá se, když SchoolContext byl inicializován, ale před tím, než byl model zabezpečen a použit k inicializaci kontextu.
    • Je vyžadováno, protože v pozdější části kurzu Student bude mít entita odkazy na ostatní entity.

Doufáme, že tento problém vyřešíme v budoucí verzi.

Program.cs

ASP.NET Core je postaven na injektování závislostí. Služby, jako je SchoolContext, se registrují pomocí injektáže závislostí při spuštění aplikace. Komponenty, které vyžadují tyto služby, například Razor Stránky, jsou poskytovány prostřednictvím parametrů konstruktoru. Kód konstruktoru, který získá instanci kontextu databáze, se zobrazí později v kurzu.

Nástroj pro generování kostry kódu automaticky zaregistroval třídu kontextu do kontejneru pro injektáž závislostí.

Následující zvýrazněné řádky kódu byly přidány nástrojem scaffoldingu:

using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

Název připojovacího řetězce se kontextu předá voláním metody objektu DbContextOptions. Při místním vývoji konfigurační systém ASP.NET Core načítá připojovací řetězec ze souboru appsettings.json nebo appsettings.Development.json.

Přidání filtru výjimek databáze

Přidejte AddDatabaseDeveloperPageExceptionFilter a UseMigrationsEndPoint jak je znázorněno v následujícím kódu:

using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
else
{
    app.UseDeveloperExceptionPage();
    app.UseMigrationsEndPoint();
}

Přidejte balíček NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.

V konzole Správce balíčků zadejte následující příkaz, který přidá balíček NuGet:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore

Balíček NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore poskytuje middleware pro ASP.NET Core pro chybové stránky pro Entity Framework Core. Tento middleware pomáhá zjišťovat a diagnostikovat chyby při migracích Entity Framework Core.

AddDatabaseDeveloperPageExceptionFilter poskytuje užitečné informace o chybách migrací EF v vývojovém prostředí.

Vytvoření databáze

Aktualizujte Program.cs tak, aby se databáze vytvořila, pokud neexistuje:

using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
else
{
    app.UseDeveloperExceptionPage();
    app.UseMigrationsEndPoint();
}

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    var context = services.GetRequiredService<SchoolContext>();
    context.Database.EnsureCreated();
    // DbInitializer.Initialize(context);
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Metoda EnsureCreated neprobíná žádnou akci, pokud existuje databáze pro kontext. Pokud žádná databáze neexistuje, vytvoří databázi a schéma. EnsureCreated umožňuje následující pracovní postup pro zpracování změn datového modelu:

  • Odstraňte databázi. Všechna existující data se ztratí.
  • Změňte datový model. Můžete například přidat EmailAddress pole.
  • Spustit aplikaci.
  • EnsureCreated vytvoří databázi s novým schématem.

Tento pracovní postup funguje v rané fázi vývoje, když se schéma rychle vyvíjí, pokud data nemusí být zachována. Situace se liší, když je potřeba zachovat data zadaná do databáze. V takovém případě použijte migrace.

Později v sérii tutoriálů se odstraní databáze vytvořená pomocí EnsureCreated a místo ní se použijí migrace. Databázi vytvořenou pomocí EnsureCreated nelze aktualizovat pomocí migrací.

Otestování aplikace

  • Spustit aplikaci.
  • Vyberte odkaz Studenti a pak vytvořte nový.
  • Otestujte odkazy Upravit, Podrobnosti a Odstranit.

Naplňte databázi počátečními daty

Metoda EnsureCreated vytvoří prázdnou databázi. Tato část přidá kód, který naplní databázi testovacími daty.

Vytvořte Data/DbInitializer.cs pomocí následujícího kódu:

using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            // Look for any students.
            if (context.Students.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
                new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2019-09-01")},
                new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")},
                new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")}
            };

            context.Students.AddRange(students);
            context.SaveChanges();

            var courses = new Course[]
            {
                new Course{CourseID=1050,Title="Chemistry",Credits=3},
                new Course{CourseID=4022,Title="Microeconomics",Credits=3},
                new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
                new Course{CourseID=1045,Title="Calculus",Credits=4},
                new Course{CourseID=3141,Title="Trigonometry",Credits=4},
                new Course{CourseID=2021,Title="Composition",Credits=3},
                new Course{CourseID=2042,Title="Literature",Credits=4}
            };

            context.Courses.AddRange(courses);
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
                new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
                new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
                new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
                new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
                new Enrollment{StudentID=3,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
                new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
                new Enrollment{StudentID=6,CourseID=1045},
                new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };

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

Kód zkontroluje, jestli v databázi nejsou žádní studenti. Pokud nejsou žádní studenti, přidá do databáze testovací data. Vytvoří testovací data v polích místo List<T> kolekcí pro optimalizaci výkonu.

  • V Program.cs odstraňte // z řádku DbInitializer.Initialize:
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    var context = services.GetRequiredService<SchoolContext>();
    context.Database.EnsureCreated();
    DbInitializer.Initialize(context);
}
  • Pokud je aplikace spuštěná, zastavte ji a v konzole Správce balíčků (PMC) spusťte následující příkaz:

    Drop-Database -Confirm
    
    
  • Odpovězte pomocí Y, chcete-li odstranit databázi.

  • Restartujte aplikaci.
  • Výběrem stránky Studenti zobrazíte počáteční data.

Zobrazení databáze

  • V aplikaci Visual Studio otevřete v nabídce Zobrazení nástroj Průzkumník objektů SQL Serveru (SSOX).
  • V nástroji SSOX vyberte (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}. Název databáze se generuje z dříve zadaného názvu kontextu, pomlčky a identifikátoru GUID.
  • Rozbalte uzel Tabulky.
  • Klikněte pravým tlačítkem myši na tabulku Student a kliknutím na Zobrazit data zobrazte sloupce vytvořené a řádky vložené do tabulky.
  • Klikněte pravým tlačítkem myši na tabulku Student a kliknutím na Zobrazit kód zobrazte, jak se Student model mapuje na Student schéma tabulky.

Asynchronní metody EF ve webových aplikacích ASP.NET Core

Asynchronní programování je výchozí režim pro ASP.NET Core a EF Core.

Webový server má k dispozici omezený počet vláken a v situacích s vysokým zatížením se můžou používat všechna dostupná vlákna. Když k tomu dojde, server nemůže zpracovávat nové požadavky, dokud se vlákna neuvolní. V synchronním kódu může být mnoho vláken svázané, zatímco nefungují, protože čekají na dokončení vstupně-výstupních operací. Když proces čeká na dokončení vstupně-výstupních operací, v asynchronním kódu se jeho vlákno uvolní, aby server používal ke zpracování dalších požadavků. V důsledku toho asynchronní kód umožňuje efektivnější použití serverových prostředků a server dokáže zpracovat větší provoz bez zpoždění.

Asynchronní kód zavádí v době běhu malé režijní náklady. V situacích s nízkým provozem je dopad na výkon zanedbatelný, zatímco v situacích s vysokým provozem je potenciální zlepšení výkonu značné.

V následujícím kódu klíčové slovo async, návratová hodnota Task, klíčové slovo await a metoda ToListAsync způsobují, že se kód provádí asynchronně.

public async Task OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
}
  • Klíčové async slovo říká kompilátoru, aby:
    • Vygenerujte callbacky pro části kódu v těle metody.
    • Vytvořte vrácený objekt Task .
  • Typ návratové hodnoty Task představuje probíhající operaci.
  • Klíčové await slovo způsobí, že kompilátor rozdělí metodu do dvou částí. První část končí operací, která se spouští asynchronně. Druhá část se vloží do metody zpětného volání, která se volá při dokončení operace.
  • ToListAsync je asynchronní verze ToList metody rozšíření.

Na co je třeba pamatovat při psaní asynchronního kódu, který používá EF Core:

  • Asynchronně se spustí pouze příkazy, které způsobují odeslání dotazů nebo příkazů do databáze. To zahrnuje ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsynca SaveChangesAsync. Nezahrnuje příkazy, které pouze mění IQueryable, například var students = context.Students.Where(s => s.LastName == "Davolio").
  • Kontext EF Core není bezpečný pro vlákno: Nepokoušejte se paralelně provádět více operací.
  • Chcete-li využít výkonnostních výhod asynchronního kódu, ověřte, zda balíčky knihoven (například pro stránkování) používají async, pokud volají metody EF Core, které odesílají dotazy do databáze.

Další informace o asynchronním programování v .NET najdete v článcích Přehled asynchronního programování a Asynchronní programování pomocí async a await.

Warning

Asynchronní implementace Microsoft.Data.SqlClient obsahuje některé známé problémy (#593, #601 a další). Pokud dochází k neočekávaným problémům s výkonem, zkuste místo toho použít spuštění příkazu synchronizace, zejména při práci s velkými textovými nebo binárními hodnotami.

Důležité informace o výkonu

Obecně platí, že webová stránka by neměla načítat libovolný počet řádků. Dotaz by měl používat stránkování nebo omezení počtu výsledků. Předchozí dotaz může například použít Take k omezení vrácených řádků:

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

Při výčtu velké tabulky v zobrazení mohla být vrácena částečně vytvořená odpověď HTTP 200, pokud v průběhu výčtu došlo k databázové výjimce.

Stránkování je popsáno později v tomto kurzu.

Další informace najdete v tématu Důležité informace o výkonu (EF).

Další kroky

Použití SQLite pro vývoj, SQL Server pro produkční prostředí

Toto je první v řadě kurzů, které ukazují, jak používat Entity Framework (EF) Core v aplikaci ASP.NET Core Razor Pages . Tyto kurzy slouží k vytvoření webu pro fiktivní univerzitu Contoso. Web obsahuje funkce, jako je přijetí studentů, vytvoření kurzu a zadání instruktora. Tento kurz využívá přístup code-first. Informace o sledování tohoto kurzu s využitím prvního přístupu k databázi najdete v tomto problému na GitHubu.

Stáhněte nebo zobrazte dokončenou aplikaci.Pokyny ke stažení

Prerequisites

  • Pokud se Razor stránkami teprve začínáte, projděte si před zahájením tohoto kurzu sérii kurzů Začínáme s Razor Pages.

Databázové stroje

Pokyny pro Visual Studio používají SQL Server LocalDB, verzi SQL Serveru Express, která běží jenom ve Windows.

Troubleshooting

Pokud narazíte na problém, který nemůžete vyřešit, porovnejte kód s dokončeným projektem. Dobrý způsob, jak získat pomoc, je odesláním otázky na StackOverflow.com pomocí značky ASP.NET Core nebo značkyEF Core.

Ukázková aplikace

Aplikace vytvořená v těchto kurzech je základní web pro vysokoškoláky. Uživatelé můžou zobrazit a aktualizovat informace o studentech, kurzech a instruktorech. Zde je několik obrazovek vytvořených v tomto kurzu.

Indexová stránka studentů

Stránka pro úpravu studentů

Styl uživatelského rozhraní tohoto webu je založený na předdefinovaných šablonách projektů. Tento kurz se zaměřuje na použití EF Core s ASP.NET Core, nikoli na přizpůsobení uživatelského rozhraní.

Volitelné: Sestavení ukázkového stažení

Tento krok je nepovinný. Sestavení dokončené aplikace se doporučuje, když máte problémy, které nemůžete vyřešit. Pokud narazíte na problém, který nemůžete vyřešit, porovnejte kód s dokončeným projektem. Pokyny ke stažení

Výběrem ContosoUniversity.csproj otevřete projekt.

  • Zkompilujte projekt.
  • V konzole Správce balíčků (PMC) spusťte následující příkaz:
Update-Database

Spusťte projekt, aby se databáze naplnila počátečními daty.

Vytvoření projektu webové aplikace

  1. Spusťte Visual Studio a vyberte Vytvořit nový projekt.
  2. V dialogovém okně Vytvořit nový projekt vyberte ASP.NET Core Web Application>Další.
  3. V dialogovém okně Konfigurovat nový projekt zadejte ContosoUniversity název projektu. Je důležité použít tento přesný název včetně použití velkých písmen, aby se každý namespace při kopírování kódu shodoval.
  4. Vyberte Vytvořit.
  5. V dialogovém okně Vytvořit novou webovou aplikaci ASP.NET Core vyberte:
    1. .NET Core a ASP.NET Core 5.0 v rozevíracích seznamech
    2. ASP.NET Core Web App.
    3. VytvořitDialogové okno Nový projekt ASP.NET Core

Nastavení stylu webu

Zkopírujte a vložte do Pages/Shared/_Layout.cshtml souboru následující kód:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Contoso University</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">Contoso University</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/About">About</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">Students</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Courses/Index">Courses</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Instructors/Index">Instructors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Departments/Index">Departments</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

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

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

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

Soubor rozvržení určuje záhlaví, zápatí a menu webu. Předchozí kód provede následující změny:

  • Každý výskyt "ContosoUniversity" změňte na "Contoso University". Existují tři výskyty.
  • Položky nabídky Home a Privacy byly odstraněny.
  • Položky jsou přidány pro About, Students, Courses, Instructors a Departments.

Nahraďte Pages/Index.cshtmlobsah souboru následujícím kódem:

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

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

Předchozí kód nahradí text o ASP.NET Core textem o této aplikaci.

Spuštěním aplikace ověřte, že se zobrazí domovská stránka.

Datový model

Následující části vytvoří datový model:

Diagram datového modelu course-enrollment-student

Student se může zaregistrovat do libovolného počtu kurzů a kurz může mít v něm zaregistrovaný libovolný počet studentů.

Entita Studenta

Diagram entit studentů

  • Ve složce projektu vytvořte složku Models .

  • Vytvořte Models/Student.cs pomocí následujícího kódu:

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

Vlastnost ID se stane sloupcem primárního klíče v tabulce databáze, která odpovídá této třídě. Ve výchozím nastavení EF Core interpretuje vlastnost s názvem ID nebo classnameID jako primární klíč. Takže automaticky rozpoznaný alternativní název primárního klíče třídy Student je StudentID. Další informace najdete v tématu EF Core – Klíče.

Vlastnost Enrollments je navigační vlastnost. Vlastnosti navigace obsahují další entity, které souvisejí s touto entitou. V tomto případě Enrollments vlastnost Student entity obsahuje všechny Enrollment entity, které se vztahují k tomuto studentu. Pokud má například řádek Student v databázi dva související řádky registrace, Enrollments navigační vlastnost obsahuje tyto dvě entity registrace.

V databázi se řádek Registrace vztahuje k řádku Student, pokud jeho StudentID sloupec obsahuje hodnotu ID studenta. Předpokládejme například, že řádek Student má ID=1. Související řádky registrace budou mít StudentID hodnotu = 1. StudentID je cizí klíč v tabulce Registrace.

Vlastnost Enrollments je definována jako ICollection<Enrollment>, protože může existovat více souvisejících entit registrace. Lze použít jiné typy kolekcí, například List<Enrollment> .HashSet<Enrollment> Když se použije ICollection<Enrollment>, EF Core ve výchozím nastavení vytvoří kolekci HashSet<Enrollment>.

entita registrace

Diagram entity registrace

Vytvořte Models/Enrollment.cs pomocí následujícího kódu:

using System.ComponentModel.DataAnnotations;

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; }
        [DisplayFormat(NullDisplayText = "No grade")]
        public Grade? Grade { get; set; }

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

Vlastnost EnrollmentID je primární klíč; tato entita používá vzor classnameID namísto samotného ID. V případě produkčního datového modelu si mnoho vývojářů zvolí jeden vzor a konzistentně ho použije. V tomto kurzu se obě používají k ilustraci toho, že obě fungují. Použití ID bez classname usnadnění implementace některých druhů změn datového modelu.

Vlastnost Grade je enum. Otazník za deklarací typu Grade značí, že vlastnost Grade může mít hodnotu null. Známka, která má hodnotu null, se liší od nulové známky – hodnota null znamená, že známka není známa nebo ještě nebyla přiřazena.

Vlastnost StudentID je cizí klíč a odpovídající navigační vlastnost je Student. Entita Enrollment je přidružená k jedné Student entitě, takže vlastnost obsahuje jednu Student entitu.

Vlastnost CourseID je cizí klíč a odpovídající navigační vlastnost je Course. Entita Enrollment je přidružená k jedné Course entitě.

EF Core interpretuje vlastnost jako cizí klíč, pokud je pojmenovaná <navigation property name><primary key property name>. NapříkladStudentID je cizím klíčem pro navigační vlastnost Student, protože primárním klíčem entity Student je ID. Vlastnosti cizího klíče lze také pojmenovat <primary key property name>. Například, CourseID protože primární klíč entity Course je CourseID.

Entita Course

Diagram entit kurzu

Vytvořte Models/Course.cs pomocí následujícího kódu:

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

Vlastnost Enrollments je navigační vlastnost. Entita Course může souviset s libovolným počtem Enrollment entit.

Atribut DatabaseGenerated umožňuje aplikaci místo vygenerování databáze zadat primární klíč.

Sestavte projekt, abyste ověřili, že nedošlo k žádným chybám kompilátoru.

Vytvořit stránky studentů

V této části se k vygenerování používá nástroj scaffolding pro ASP.NET Core:

  • Třída EF CoreDbContext. Kontext je hlavní třída, která koordinuje funkce Entity Framework pro daný datový model. Odvozuje se z třídy Microsoft.EntityFrameworkCore.DbContext.
  • Razor stránky, které zpracovávají operace vytvoření, čtení, aktualizace a odstranění (CRUD) pro entitu Student .
  • Vytvořte složku Pages/Students .
  • V Průzkumníku řešení klikněte pravým tlačítkem na složku Pages/Students a vyberte Přidat>Nová generovaná položka.
  • V dialogovém okně Přidat novou položku generátoru:
    • Na kartě vlevo vyberte Nainstalované > společné >Razor stránky
    • Vyberte Razor Stránky pomocí Entity Framework (CRUD)>ADD.
  • V dialogovém okně Přidat Razor stránky pomocí entity Framework (CRUD):
    • V rozevíracím seznamu Třída modelu vyberte Student (ContosoUniversity.Models).
    • V řádku Data context class vyberte symbol + (plus).
      • Změňte název kontextu dat tak, aby končil SchoolContext místo ContosoUniversityContext. Aktualizovaný název kontextu: ContosoUniversity.Data.SchoolContext
      • Výběrem možnosti Přidat dokončíte přidání třídy kontextu dat.
      • Výběrem možnosti Přidat dokončete dialogové okno Přidat Razor stránky .

Pokud generování uživatelského rozhraní selže s chybou 'Install the package Microsoft.VisualStudio.Web.CodeGeneration.Design and try again.', spusťte znovu nástroj pro generování uživatelského rozhraní nebo se podívejte na tento problém na GitHubu.

Automaticky se nainstalují následující balíčky:

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

Pokud předchozí krok selže, sestavte projekt a opakujte krok generování.

Proces scaffoldingu:

  • Vytvoří Razor stránky ve složce Pages/Students :
    • Create.cshtml a Create.cshtml.cs
    • Delete.cshtml a Delete.cshtml.cs
    • Details.cshtml a Details.cshtml.cs
    • Edit.cshtml a Edit.cshtml.cs
    • Index.cshtml a Index.cshtml.cs
  • Vytvoří Data/SchoolContext.cs.
  • Přidá kontext do injektáže závislostí v Startup.cssouboru .
  • Přidá připojovací řetězec databáze do appsettings.json.

Připojovací řetězec databáze

Nástroj pro generování pomocného kódu vygeneruje v souboru appsettings.json připojovací řetězec.

Připojovací řetězec určuje SQL Server LocalDB:

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

LocalDB je zjednodušená verze databázového stroje SQL Server Express a je určená pro vývoj aplikací, nikoli pro produkční použití. Ve výchozím nastavení LocalDB vytvoří .mdf soubory v C:/Users/<user> adresáři.

Aktualizace třídy kontextu databáze

Hlavní třída, která koordinuje EF Core funkce pro daný datový model, je třída kontextu databáze. Kontext je odvozen z Microsoft.EntityFrameworkCore.DbContext. Kontext určuje, které entity jsou součástí datového modelu. V tomto projektu má třída název SchoolContext.

Aktualizujte Data/SchoolContext.cs následujícím kódem:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

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

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

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

Předchozí kód se změní z jednotného čísla DbSet<Student> Student na množné číslo DbSet<Student> Students. Pokud chcete, aby Razor kód Stránky odpovídal novému DBSet názvu, proveďte globální změnu z: _context.Student. k: _context.Students.

Existuje 8 výskytů.

Vzhledem k tomu, že sada entit obsahuje více entit, mnoho vývojářů dává přednost DBSet názvům vlastností v množném čísle.

Zvýrazněný kód:

  • Vytvoří DbSet<TEntity> vlastnost pro každou sadu entit. V terminologii EF Core:
    • Sada entit obvykle odpovídá databázové tabulce.
    • Entita odpovídá řádku v tabulce.
  • Zavolá metodu OnModelCreating. OnModelCreating:
    • Volá se, když SchoolContext byl inicializován, ale před tím, než byl model zabezpečen a použit k inicializaci kontextu.
    • Je vyžadováno, protože v pozdější části kurzu Student bude mít entita odkazy na ostatní entity.

Sestavte projekt, abyste ověřili, že nedošlo k žádným chybám kompilátoru.

Startup.cs

ASP.NET Core je postaven na injektování závislostí. Služby, jako je SchoolContext, se registrují pomocí injektáže závislostí při spuštění aplikace. Komponenty, které vyžadují tyto služby, například Razor Stránky, jsou poskytovány prostřednictvím parametrů konstruktoru. Kód konstruktoru, který získá instanci kontextu databáze, se zobrazí později v kurzu.

Nástroj pro generování kostry kódu automaticky zaregistroval třídu kontextu do kontejneru pro injektáž závislostí.

Následující zvýrazněné řádky kódu byly přidány nástrojem scaffoldingu:

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

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

Název připojovacího řetězce se kontextu předá voláním metody objektu DbContextOptions. V případě místního vývoje načte konfigurační systém ASP.NET Core připojovací řetězec ze appsettings.json souboru.

Přidání filtru výjimek databáze

Přidejte AddDatabaseDeveloperPageExceptionFilter a UseMigrationsEndPoint jak je znázorněno v následujícím kódu:

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

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

    services.AddDatabaseDeveloperPageExceptionFilter();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Přidejte balíček NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.

V konzole Správce balíčků zadejte následující příkaz, který přidá balíček NuGet:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore

Balíček NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore poskytuje middleware pro ASP.NET Core pro chybové stránky pro Entity Framework Core. Tento middleware pomáhá zjišťovat a diagnostikovat chyby při migracích Entity Framework Core.

AddDatabaseDeveloperPageExceptionFilter poskytuje užitečné informace o chybách migrací EF v vývojovém prostředí.

Vytvoření databáze

Aktualizujte Program.cs tak, aby se databáze vytvořila, pokud neexistuje:

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

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

            CreateDbIfNotExists(host);

            host.Run();
        }

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

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

Metoda EnsureCreated neprobíná žádnou akci, pokud existuje databáze pro kontext. Pokud žádná databáze neexistuje, vytvoří databázi a schéma. EnsureCreated umožňuje následující pracovní postup pro zpracování změn datového modelu:

  • Odstraňte databázi. Všechna existující data se ztratí.
  • Změňte datový model. Můžete například přidat EmailAddress pole.
  • Spustit aplikaci.
  • EnsureCreated vytvoří databázi s novým schématem.

Tento pracovní postup funguje v rané fázi vývoje, když se schéma rychle vyvíjí, pokud data nemusí být zachována. Situace se liší, když je potřeba zachovat data zadaná do databáze. V takovém případě použijte migrace.

Později v sérii tutoriálů se odstraní databáze vytvořená pomocí EnsureCreated a místo ní se použijí migrace. Databázi vytvořenou pomocí EnsureCreated nelze aktualizovat pomocí migrací.

Otestování aplikace

  • Spustit aplikaci.
  • Vyberte odkaz Studenti a pak vytvořte nový.
  • Otestujte odkazy Upravit, Podrobnosti a Odstranit.

Naplňte databázi počátečními daty

Metoda EnsureCreated vytvoří prázdnou databázi. Tato část přidá kód, který naplní databázi testovacími daty.

Vytvořte Data/DbInitializer.cs pomocí následujícího kódu:

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

namespace ContosoUniversity.Data
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            // Look for any students.
            if (context.Students.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
                new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2019-09-01")},
                new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")},
                new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")}
            };

            context.Students.AddRange(students);
            context.SaveChanges();

            var courses = new Course[]
            {
                new Course{CourseID=1050,Title="Chemistry",Credits=3},
                new Course{CourseID=4022,Title="Microeconomics",Credits=3},
                new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
                new Course{CourseID=1045,Title="Calculus",Credits=4},
                new Course{CourseID=3141,Title="Trigonometry",Credits=4},
                new Course{CourseID=2021,Title="Composition",Credits=3},
                new Course{CourseID=2042,Title="Literature",Credits=4}
            };

            context.Courses.AddRange(courses);
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
                new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
                new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
                new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
                new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
                new Enrollment{StudentID=3,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
                new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
                new Enrollment{StudentID=6,CourseID=1045},
                new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };

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

Kód zkontroluje, jestli v databázi nejsou žádní studenti. Pokud nejsou žádní studenti, přidá do databáze testovací data. Vytvoří testovací data v polích místo List<T> kolekcí pro optimalizaci výkonu.

  • V Program.cs odstraňte // z řádku DbInitializer.Initialize:

      context.Database.EnsureCreated();
      DbInitializer.Initialize(context);
    
  • Pokud je aplikace spuštěná, zastavte ji a v konzole Správce balíčků (PMC) spusťte následující příkaz:

    Drop-Database -Confirm
    
    
  • Odpovězte pomocí Y, chcete-li odstranit databázi.

  • Restartujte aplikaci.
  • Výběrem stránky Studenti zobrazíte počáteční data.

Zobrazení databáze

  • V aplikaci Visual Studio otevřete v nabídce Zobrazení nástroj Průzkumník objektů SQL Serveru (SSOX).
  • V nástroji SSOX vyberte (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}. Název databáze se generuje z dříve zadaného názvu kontextu, pomlčky a identifikátoru GUID.
  • Rozbalte uzel Tabulky.
  • Klikněte pravým tlačítkem myši na tabulku Student a kliknutím na Zobrazit data zobrazte sloupce vytvořené a řádky vložené do tabulky.
  • Klikněte pravým tlačítkem myši na tabulku Student a kliknutím na Zobrazit kód zobrazte, jak se Student model mapuje na Student schéma tabulky.

Asynchronní kód

Asynchronní programování je výchozí režim pro ASP.NET Core a EF Core.

Webový server má k dispozici omezený počet vláken a v situacích s vysokým zatížením se můžou používat všechna dostupná vlákna. Když k tomu dojde, server nemůže zpracovávat nové požadavky, dokud se vlákna neuvolní. V synchronním kódu může být mnoho vláken svázané, zatímco nefungují, protože čekají na dokončení vstupně-výstupních operací. Když proces čeká na dokončení vstupně-výstupních operací, v asynchronním kódu se jeho vlákno uvolní, aby server používal ke zpracování dalších požadavků. V důsledku toho asynchronní kód umožňuje efektivnější použití serverových prostředků a server dokáže zpracovat větší provoz bez zpoždění.

Asynchronní kód zavádí v době běhu malé režijní náklady. V situacích s nízkým provozem je dopad na výkon zanedbatelný, zatímco v situacích s vysokým provozem je potenciální zlepšení výkonu značné.

V následujícím kódu klíčové slovo async, návratová hodnota Task, klíčové slovo await a metoda ToListAsync způsobují, že se kód provádí asynchronně.

public async Task OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
}
  • Klíčové async slovo říká kompilátoru, aby:
    • Vygenerujte callbacky pro části kódu v těle metody.
    • Vytvořte vrácený objekt Task .
  • Typ návratové hodnoty Task představuje probíhající operaci.
  • Klíčové await slovo způsobí, že kompilátor rozdělí metodu do dvou částí. První část končí operací, která se spouští asynchronně. Druhá část se vloží do metody zpětného volání, která se volá při dokončení operace.
  • ToListAsync je asynchronní verze ToList metody rozšíření.

Na co je třeba pamatovat při psaní asynchronního kódu, který používá EF Core:

  • Asynchronně se spustí pouze příkazy, které způsobují odeslání dotazů nebo příkazů do databáze. To zahrnuje ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsynca SaveChangesAsync. Nezahrnuje příkazy, které pouze mění IQueryable, například var students = context.Students.Where(s => s.LastName == "Davolio").
  • Kontext EF Core není bezpečný pro vlákno: Nepokoušejte se paralelně provádět více operací.
  • Chcete-li využít výkonnostních výhod asynchronního kódu, ověřte, zda balíčky knihoven (například pro stránkování) používají async, pokud volají metody EF Core, které odesílají dotazy do databáze.

Další informace o asynchronním programování v .NET najdete v článcích Přehled asynchronního programování a Asynchronní programování pomocí async a await.

Důležité informace o výkonu

Obecně platí, že webová stránka by neměla načítat libovolný počet řádků. Dotaz by měl používat stránkování nebo omezení počtu výsledků. Předchozí dotaz může například použít Take k omezení vrácených řádků:

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

Při výčtu velké tabulky v zobrazení mohla být vrácena částečně vytvořená odpověď HTTP 200, pokud v průběhu výčtu došlo k databázové výjimce.

MaxModelBindingCollectionSize výchozí hodnota je 1024. Následující kód nastaví MaxModelBindingCollectionSize:

public void ConfigureServices(IServiceCollection services)
{
    var myMaxModelBindingCollectionSize = Convert.ToInt32(
                Configuration["MyMaxModelBindingCollectionSize"] ?? "100");

    services.Configure<MvcOptions>(options =>
           options.MaxModelBindingCollectionSize = myMaxModelBindingCollectionSize);

    services.AddRazorPages();

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

    services.AddDatabaseDeveloperPageExceptionFilter();
}

Viz Configuration, kde najdete informace o nastavení konfigurace, jako je MyMaxModelBindingCollectionSize.

Stránkování je popsáno později v tomto kurzu.

Další informace najdete v tématu Důležité informace o výkonu (EF).

Protokolování SQL v Entity Framework Core

Konfiguraci protokolování obvykle zajišťuje oddíl Logging souborů appsettings.{Environment}.json. Pokud chcete protokolovat příkazy SQL, přidejte "Microsoft.EntityFrameworkCore.Database.Command": "Information" do appsettings.Development.json souboru:

{
  "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": "*"
}

V předchozím kódu JSON se příkazy SQL zobrazí na příkazovém řádku a v okně výstupu sady Visual Studio.

Další informace najdete v následujících zdrojích informací:

Další kroky

Použití SQLite pro vývoj, SQL Server pro produkční prostředí

Toto je první v řadě kurzů, které ukazují, jak používat Entity Framework (EF) Core v aplikaci ASP.NET Core Razor Pages . Tyto kurzy slouží k vytvoření webu pro fiktivní univerzitu Contoso. Web obsahuje funkce, jako je přijetí studentů, vytvoření kurzu a zadání instruktora. Tento kurz využívá přístup code-first. Informace o sledování tohoto kurzu s využitím prvního přístupu k databázi najdete v tomto problému na GitHubu.

Stáhněte nebo zobrazte dokončenou aplikaci.Pokyny ke stažení

Prerequisites

  • Pokud se Razor stránkami teprve začínáte, projděte si před zahájením tohoto kurzu sérii kurzů Začínáme s Razor Pages.

Databázové stroje

Pokyny pro Visual Studio používají SQL Server LocalDB, verzi SQL Serveru Express, která běží jenom ve Windows.

Pokyny pro Visual Studio Code používají SQLite, databázový stroj pro různé platformy.

Pokud se rozhodnete používat SQLite, stáhněte a nainstalujte nástroj třetí strany pro správu a zobrazení databáze SQLite, například prohlížeč databáze pro SQLite.

Troubleshooting

Pokud narazíte na problém, který nemůžete vyřešit, porovnejte kód s dokončeným projektem. Dobrý způsob, jak získat pomoc, je odesláním otázky na StackOverflow.com pomocí značky ASP.NET Core nebo značkyEF Core.

Ukázková aplikace

Aplikace vytvořená v těchto kurzech je základní web pro vysokoškoláky. Uživatelé můžou zobrazit a aktualizovat informace o studentech, kurzech a instruktorech. Zde je několik obrazovek vytvořených v tomto kurzu.

Indexová stránka studentů

Stránka pro úpravu studentů

Styl uživatelského rozhraní tohoto webu je založený na předdefinovaných šablonách projektů. Tento kurz se zaměřuje na to, jak používat EF Core, nikoli jak přizpůsobit uživatelské rozhraní.

Pokud chcete získat zdrojový kód dokončeného projektu, postupujte podle odkazu v horní části stránky. Složka cu30 obsahuje kód pro verzi kurzu ASP.NET Core 3.0. Soubory, které odrážejí stav kódu pro kurzy 1-7, najdete ve složce cu30snapshots .

Spuštění aplikace po stažení dokončeného projektu:

  • Zkompilujte projekt.

  • V konzole Správce balíčků (PMC) spusťte následující příkaz:

    Update-Database
    
  • Spusťte projekt, aby se databáze naplnila počátečními daty.

Vytvoření projektu webové aplikace

  • V nabídce Soubor aplikace Visual Studio vyberte možnost Nový>projekt.
  • Vyberte ASP.NET Základní webová aplikace.
  • Pojmenujte projekt ContosoUniversity. Je důležité použít tento přesný název včetně velkých písmen, aby se obory názvů při kopírování a vkládání kódu shodovaly.
  • V rozevíracích sadě vyberte .NET Core a ASP.NET Core 3.0 a pak vyberte Webová aplikace.

Nastavení stylu webu

Nastavení záhlaví, zápatí webu a nabídky aktualizací Pages/Shared/_Layout.cshtml:

  • Změňte každý výskyt "ContosoUniversity" na "Contoso University". Existují tři výskyty.

  • Odstraňte položky nabídky Home a Privacy a přidejte položky pro O aplikaci, Studenti, Kurzy, Vyučující a Katedry.

Změny jsou zvýrazněné.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Contoso University</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">Contoso University</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/About">About</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">Students</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Courses/Index">Courses</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Instructors/Index">Instructors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Departments/Index">Departments</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

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

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

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

Nahraďte Pages/Index.cshtmlobsah souboru následujícím kódem, který nahradí text o ASP.NET Core textem o této aplikaci:

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

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

Spuštěním aplikace ověřte, že se zobrazí domovská stránka.

Datový model

Následující části vytvoří datový model:

Diagram datového modelu course-enrollment-student

Student se může zaregistrovat do libovolného počtu kurzů a kurz může mít v něm zaregistrovaný libovolný počet studentů.

Entita Studenta

Diagram entit studentů

  • Ve složce projektu vytvořte složku Models .

  • Vytvořte Models/Student.cs pomocí následujícího kódu:

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

Vlastnost ID se stane sloupcem primárního klíče v tabulce databáze, která odpovídá této třídě. Ve výchozím nastavení EF Core interpretuje vlastnost s názvem ID nebo classnameID jako primární klíč. Takže automaticky rozpoznaný alternativní název primárního klíče třídy Student je StudentID. Další informace najdete v tématu EF Core – Klíče.

Vlastnost Enrollments je navigační vlastnost. Vlastnosti navigace obsahují další entity, které souvisejí s touto entitou. V tomto případě Enrollments vlastnost Student entity obsahuje všechny Enrollment entity, které se vztahují k tomuto studentu. Pokud má například řádek Student v databázi dva související řádky registrace, Enrollments navigační vlastnost obsahuje tyto dvě entity registrace.

V databázi se řádek Registrace vztahuje k řádku Student, pokud jeho sloupec StudentID obsahuje hodnotu ID studenta. Předpokládejme například, že řádek Student má ID=1. Související řádky registrace budou mít ID studenta = 1. ID studenta je cizí klíč v tabulce Registrace.

Vlastnost Enrollments je definována jako ICollection<Enrollment>, protože může existovat více souvisejících entit registrace. Můžete použít jiné typy kolekcí, například List<Enrollment> nebo HashSet<Enrollment>. Když se použije ICollection<Enrollment>, EF Core ve výchozím nastavení vytvoří kolekci HashSet<Enrollment>.

entita registrace

Diagram entity registrace

Vytvořte Models/Enrollment.cs pomocí následujícího kódu:

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

Vlastnost EnrollmentID je primární klíč; tato entita používá vzor classnameID namísto samotného ID. Pro produkční datový model zvolte jeden vzor a používejte ho konzistentně. V tomto kurzu se obě používají k ilustraci toho, že obě fungují. Použití ID bez classname usnadnění implementace některých druhů změn datového modelu.

Vlastnost Grade je enum. Otazník za deklarací typu Grade značí, že vlastnost Grade může mít hodnotu null. Známka, která má hodnotu null, se liší od nulové známky – hodnota null znamená, že známka není známa nebo ještě nebyla přiřazena.

Vlastnost StudentID je cizí klíč a odpovídající navigační vlastnost je Student. Entita Enrollment je přidružená k jedné Student entitě, takže vlastnost obsahuje jednu Student entitu.

Vlastnost CourseID je cizí klíč a odpovídající navigační vlastnost je Course. Entita Enrollment je přidružená k jedné Course entitě.

EF Core interpretuje vlastnost jako cizí klíč, pokud je pojmenovaná <navigation property name><primary key property name>. NapříkladStudentID je cizím klíčem pro navigační vlastnost Student, protože primárním klíčem entity Student je ID. Vlastnosti cizího klíče lze také pojmenovat <primary key property name>. Například, CourseID protože primární klíč entity Course je CourseID.

Entita Course

Diagram entit kurzu

Vytvořte Models/Course.cs pomocí následujícího kódu:

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

Vlastnost Enrollments je navigační vlastnost. Entita Course může souviset s libovolným počtem Enrollment entit.

Atribut DatabaseGenerated umožňuje aplikaci místo vygenerování databáze zadat primární klíč.

Sestavte projekt, abyste ověřili, že nedošlo k žádným chybám kompilátoru.

Vytvořit stránky studentů

V této části použijete nástroj scaffolding ASP.NET Core k vygenerování:

  • Třída EF Corekontextu. Kontext je hlavní třída, která koordinuje funkce Entity Framework pro daný datový model. Odvozuje se z třídy Microsoft.EntityFrameworkCore.DbContext.
  • Razor stránky, které zpracovávají operace vytvoření, čtení, aktualizace a odstranění (CRUD) pro entitu Student .
  • Ve složce Pages vytvořte složku Students.
  • V Průzkumníku řešení klikněte pravým tlačítkem na složku Pages/Students a vyberte Přidat>Nová generovaná položka.
  • V dialogovém okně Add Scaffold vyberte RazorStránky používající Entity Framework (CRUD)>PŘIDAT.
  • V dialogovém okně Přidat Razor stránky pomocí entity Framework (CRUD):
    • V rozevíracím seznamu Třída modelu vyberte Student (ContosoUniversity.Models).
    • V řádku Data context class vyberte symbol + (plus).
    • Změňte název kontextu dat z ContosoUniversity.Models.ContosoUniversityContext na ContosoUniversity.Data.SchoolContext.
    • Vyberte Přidat.

Automaticky se nainstalují následující balíčky:

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

Pokud máte problém s předchozím krokem, sestavte projekt a zopakujte krok scaffoldu.

Proces scaffoldingu:

  • Vytvoří Razor stránky ve složce Pages/Students :
    • Create.cshtml a Create.cshtml.cs
    • Delete.cshtml a Delete.cshtml.cs
    • Details.cshtml a Details.cshtml.cs
    • Edit.cshtml a Edit.cshtml.cs
    • Index.cshtml a Index.cshtml.cs
  • Vytvoří Data/SchoolContext.cs.
  • Přidá kontext do injektáže závislostí v Startup.cssouboru .
  • Přidá připojovací řetězec databáze do appsettings.json.

Připojovací řetězec databáze

Soubor appsettings.json určuje připojovací řetězec SQL Server LocalDB.

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

LocalDB je zjednodušená verze databázového stroje SQL Server Express a je určená pro vývoj aplikací, nikoli pro produkční použití. Ve výchozím nastavení LocalDB vytvoří .mdf soubory v C:/Users/<user> adresáři.

Aktualizace třídy kontextu databáze

Hlavní třída, která koordinuje EF Core funkce pro daný datový model, je třída kontextu databáze. Kontext je odvozen z Microsoft.EntityFrameworkCore.DbContext. Kontext určuje, které entity jsou součástí datového modelu. V tomto projektu má třída název SchoolContext.

Aktualizujte Data/SchoolContext.cs následujícím kódem:

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

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

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

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

Zvýrazněný kód vytvoří DbSet<TEntity> vlastnost pro každou sadu entit. V terminologii EF Core:

  • Sada entit obvykle odpovídá databázové tabulce.
  • Entita odpovídá řádku v tabulce.

Vzhledem k tomu, že sada entit obsahuje více entit, vlastnosti typu DBSet by měly mít názvy v množném čísle. Vzhledem k tomu, že nástroj pro generování kostry kódu vytvořilStudent objekt DBSet, tento krok jej změní na množné číslo Students.

Pokud chcete, aby Razor kód Pages odpovídal novému názvu dbSet, proveďte globální změnu v celém projektu _context.Student na _context.Students. Existuje 8 výskytů.

Sestavte projekt, abyste ověřili, že nedošlo k žádným chybám kompilátoru.

Startup.cs

ASP.NET Core je postaven na injektování závislostí. Služby (například EF Core kontext databáze) se během spouštění aplikace registrují pomocí injektáže závislostí. Komponentám, které tyto služby vyžadují (například Razor stránky), jsou tyto služby poskytovány prostřednictvím parametrů konstruktoru. Kód konstruktoru, který získá instanci kontextu databáze, se zobrazí později v kurzu.

Nástroj pro generování kostry kódu automaticky zaregistroval třídu kontextu do kontejneru pro injektáž závislostí.

  • V ConfigureServices byly zvýrazněné řádky přidány nástrojem scaffolderu:

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

Název připojovacího řetězce se kontextu předá voláním metody objektu DbContextOptions. V případě místního vývoje načte konfigurační systém ASP.NET Core připojovací řetězec ze appsettings.json souboru.

Vytvoření databáze

Aktualizujte Program.cs tak, aby se databáze vytvořila, pokud neexistuje:

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

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

            CreateDbIfNotExists(host);

            host.Run();
        }

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

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

Metoda EnsureCreated neprobíná žádnou akci, pokud existuje databáze pro kontext. Pokud žádná databáze neexistuje, vytvoří databázi a schéma. EnsureCreated umožňuje následující pracovní postup pro zpracování změn datového modelu:

  • Odstraňte databázi. Všechna existující data se ztratí.
  • Změňte datový model. Můžete například přidat EmailAddress pole.
  • Spustit aplikaci.
  • EnsureCreated vytvoří databázi s novým schématem.

Tento postup funguje dobře v rané fázi vývoje, když se schéma rychle mění, pokud nepotřebujete zachovat data. Situace se liší, když je potřeba zachovat data zadaná do databáze. V takovém případě použijte migrace.

Později v sérii kurzů odstraníte databázi vytvořenou pomocí EnsureCreated a místo ní použijete migrace. Databázi vytvořenou pomocí EnsureCreated nelze aktualizovat pomocí migrací.

Otestování aplikace

  • Spustit aplikaci.
  • Vyberte odkaz Studenti a pak vytvořte nový.
  • Otestujte odkazy Upravit, Podrobnosti a Odstranit.

Naplňte databázi počátečními daty

Metoda EnsureCreated vytvoří prázdnou databázi. Tato část přidá kód, který naplní databázi testovacími daty.

Vytvořte Data/DbInitializer.cs pomocí následujícího kódu:

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

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

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

            var students = new Student[]
            {
                new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2019-09-01")},
                new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")},
                new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")},
                new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")},
                new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")}
            };

            context.Students.AddRange(students);
            context.SaveChanges();

            var courses = new Course[]
            {
                new Course{CourseID=1050,Title="Chemistry",Credits=3},
                new Course{CourseID=4022,Title="Microeconomics",Credits=3},
                new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
                new Course{CourseID=1045,Title="Calculus",Credits=4},
                new Course{CourseID=3141,Title="Trigonometry",Credits=4},
                new Course{CourseID=2021,Title="Composition",Credits=3},
                new Course{CourseID=2042,Title="Literature",Credits=4}
            };

            context.Courses.AddRange(courses);
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
                new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
                new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
                new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
                new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
                new Enrollment{StudentID=3,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
                new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
                new Enrollment{StudentID=6,CourseID=1045},
                new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };

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

Kód zkontroluje, jestli v databázi nejsou žádní studenti. Pokud nejsou žádní studenti, přidá do databáze testovací data. Vytvoří testovací data v polích místo List<T> kolekcí pro optimalizaci výkonu.

  • V Program.cs nahraďte volání EnsureCreated voláním DbInitializer.Initialize:

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

Pokud je aplikace spuštěná, zastavte ji a v konzole Správce balíčků (PMC) spusťte následující příkaz:

Drop-Database
  • Restartujte aplikaci.

  • Výběrem stránky Studenti zobrazíte počáteční data.

Zobrazení databáze

  • V aplikaci Visual Studio otevřete v nabídce Zobrazení nástroj Průzkumník objektů SQL Serveru (SSOX).
  • V nástroji SSOX vyberte (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}. Název databáze se vytvoří z názvu kontextu, který jste zadali dříve, doplněného o pomlčku a identifikátor GUID.
  • Rozbalte uzel Tabulky.
  • Klikněte pravým tlačítkem myši na tabulku Student a kliknutím na Zobrazit data zobrazte sloupce vytvořené a řádky vložené do tabulky.
  • Klikněte pravým tlačítkem myši na tabulku Student a kliknutím na Zobrazit kód zobrazte, jak se Student model mapuje na Student schéma tabulky.

Asynchronní kód

Asynchronní programování je výchozí režim pro ASP.NET Core a EF Core.

Webový server má k dispozici omezený počet vláken a v situacích s vysokým zatížením se můžou používat všechna dostupná vlákna. Když k tomu dojde, server nemůže zpracovávat nové požadavky, dokud se vlákna neuvolní. V synchronním kódu může být mnoho vláken svázané, zatímco ve skutečnosti neprovádí žádnou práci, protože čekají na dokončení vstupně-výstupních operací. Když proces čeká na dokončení vstupně-výstupních operací, v asynchronním kódu se jeho vlákno uvolní, aby server používal ke zpracování dalších požadavků. V důsledku toho asynchronní kód umožňuje efektivnější použití serverových prostředků a server dokáže zpracovat větší provoz bez zpoždění.

Asynchronní kód zavádí v době běhu malé režijní náklady. V situacích s nízkým provozem je dopad na výkon zanedbatelný, zatímco v situacích s vysokým provozem je potenciální zlepšení výkonu značné.

V následujícím kódu klíčové slovo async, návratová hodnota Task<T>, klíčové slovo await a metoda ToListAsync způsobují, že se kód provádí asynchronně.

public async Task OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
}
  • Klíčové async slovo říká kompilátoru, aby:
    • Vygenerujte callbacky pro části kódu v těle metody.
    • Vytvořte vrácený objekt Task .
  • Typ návratové hodnoty Task<T> představuje probíhající operaci.
  • Klíčové await slovo způsobí, že kompilátor rozdělí metodu do dvou částí. První část končí operací, která se spouští asynchronně. Druhá část se vloží do metody zpětného volání, která se volá při dokončení operace.
  • ToListAsync je asynchronní verze ToList metody rozšíření.

Na co je třeba pamatovat při psaní asynchronního kódu, který používá EF Core:

  • Asynchronně se spustí pouze příkazy, které způsobují odeslání dotazů nebo příkazů do databáze. To zahrnuje ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsynca SaveChangesAsync. Nezahrnuje příkazy, které pouze mění IQueryable, například var students = context.Students.Where(s => s.LastName == "Davolio").
  • Kontext EF Core není bezpečný pro vlákno: Nepokoušejte se paralelně provádět více operací.
  • Chcete-li využít výkonnostních výhod asynchronního kódu, ověřte, zda balíčky knihoven (například pro stránkování) používají async, pokud volají metody EF Core, které odesílají dotazy do databáze.

Další informace o asynchronním programování v .NET najdete v článcích Přehled asynchronního programování a Asynchronní programování pomocí async a await.

Další kroky