Tutorial: Mulai menggunakan EF Core aplikasi web MVC ASP.NET

Oleh Tom Dykstra dan Rick Anderson

Tutorial ini mengajarkan ASP.NET Core MVC dan Entity Framework Core dengan pengontrol dan tampilan. Razor Pages adalah model pemrograman alternatif. Untuk pengembangan baru, kami menyarankan Razor Pages melalui MVC dengan pengontrol dan tampilan. Lihat versi Razor Pages dari tutorial ini. Setiap tutorial mencakup beberapa materi yang tidak dicakup oleh tutorial lainnya:

Beberapa hal yang dimiliki tutorial MVC ini yang tidak dimiliki tutorial Razor Pages:

  • Mengimplementasikan pewarisan dalam model data
  • Melakukan kueri SQL mentah
  • Menggunakan LINQ dinamis untuk menyederhanakan kode

Beberapa hal yang dimiliki tutorial Razor Pages yang tidak dimiliki tutorial ini:

  • Menggunakan metode Pilih untuk memuat data terkait
  • Praktik terbaik untuk EF.

Aplikasi web sampel Contoso University menunjukkan cara membuat aplikasi web ASP.NET Core MVC menggunakan Entity Framework (EF) Core dan Visual Studio.

Aplikasi sampel adalah situs web untuk Universitas Contoso fiktif. Ini termasuk fungsionalitas seperti penerimaan siswa, pembuatan kursus, dan tugas instruktur. Ini adalah yang pertama dalam serangkaian tutorial yang menjelaskan cara membangun aplikasi sampel Contoso University.

Prasyarat

Tutorial ini belum diperbarui untuk ASP.NET Core 6 atau yang lebih baru. Instruksi tutorial tidak akan berfungsi dengan benar jika Anda membuat proyek yang menargetkan ASP.NET Core 6 atau yang lebih baru. Misalnya, templat web ASP.NET Core 6 dan yang lebih baru menggunakan model hosting minimal, yang menyaring Startup.cs dan Program.cs menjadi satu Program.cs file.

Perbedaan lain yang diperkenalkan dalam .NET 6 adalah fitur NRT (jenis referensi nullable). Templat proyek mengaktifkan fitur ini secara default. Masalah dapat terjadi di mana EF menganggap properti diperlukan di .NET 6 yang dapat diubah ke null di .NET 5. Misalnya, halaman Buat Siswa akan gagal secara diam-diam Enrollments kecuali properti dibuat nullable atau tag pembantu asp-validation-summary diubah dari ModelOnly ke All.

Kami menyarankan agar Anda menginstal dan menggunakan .NET 5 SDK untuk tutorial ini. Hingga tutorial ini diperbarui, lihat Razor Halaman dengan Entity Framework Core di ASP.NET Core - Tutorial 1 dari 8 tentang cara menggunakan Kerangka Kerja Entitas dengan ASP.NET Core 6 atau yang lebih baru.

Mesin database

Instruksi Visual Studio menggunakan SQL Server LocalDB, versi SQL Server Express yang hanya berjalan di Windows.

Memecahkan masalah dan memecahkan masalah

Jika Anda mengalami masalah yang tidak dapat Anda atasi, Anda umumnya dapat menemukan solusi dengan membandingkan kode Anda dengan proyek yang telah selesai. Untuk daftar kesalahan umum dan cara menyelesaikannya, lihat bagian Pemecahan Masalah dari tutorial terakhir dalam seri. Jika Anda tidak menemukan apa yang Anda butuhkan di sana, Anda dapat memposting pertanyaan ke StackOverflow.com untuk ASP.NET Core atau EF Core.

Tip

Ini adalah serangkaian tutorial 10, yang masing-masing dibangun berdasarkan apa yang dilakukan dalam tutorial sebelumnya. Pertimbangkan untuk menyimpan salinan proyek setelah setiap penyelesaian tutorial berhasil. Kemudian jika Anda mengalami masalah, Anda dapat memulai kembali dari tutorial sebelumnya alih-alih kembali ke awal seluruh seri.

Aplikasi web Contoso University

Aplikasi yang dibangun dalam tutorial ini adalah situs web universitas dasar.

Pengguna dapat melihat dan memperbarui informasi siswa, kursus, dan instruktur. Berikut adalah beberapa layar di aplikasi:

Students Index page

Students Edit page

Membuat aplikasi web

  1. Mulai Visual Studio dan pilih Buat proyek baru.
  2. Dalam dialog Buat proyek baru, pilih ASP.NET Core Web Application>Next.
  3. Dalam dialog Konfigurasikan proyek baru Anda, masukkan ContosoUniversity untuk Nama proyek. Penting untuk menggunakan nama yang tepat ini termasuk kapitalisasi, sehingga setiap namespace kecocokan saat kode disalin.
  4. Pilih Buat.
  5. Dalam dialog Buat aplikasi web ASP.NET Core baru, pilih:
    1. .NET Core dan ASP.NET Core 5.0 di menu dropdown.
    2. ASP.NET Core Web App (Model-View-Controller).
    3. BuatNew ASP.NET Core Project dialog

Menyiapkan gaya situs

Beberapa perubahan dasar menyiapkan menu situs, tata letak, dan beranda.

Buka Views/Shared/_Layout.cshtml dan buat perubahan berikut:

  • Ubah setiap kemunculan menjadi ContosoUniversityContoso University. Ada tiga kejadian.
  • Tambahkan entri menu untuk Tentang, Siswa, Kursus, Instruktur, dan Departemen, dan hapus Privacy entri menu.

Perubahan sebelumnya disorot dalam kode berikut:

<!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">
            &copy; 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>

Di Views/Home/Index.cshtml, ganti konten file dengan markup berikut:

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

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

Tekan CTRL+F5 untuk menjalankan proyek atau pilih Debug > Mulai Tanpa Debugging dari menu. Beranda ditampilkan dengan tab untuk halaman yang dibuat dalam tutorial ini.

Contoso University home page

EF Core Paket NuGet

Tutorial ini menggunakan SQL Server, dan paket penyedianya adalah Microsoft.EntityFrameworkCore.SqlServer.

Paket EF SQL Server dan dependensinya, Microsoft.EntityFrameworkCore dan Microsoft.EntityFrameworkCore.Relational, menyediakan dukungan runtime untuk EF.

Tambahkan paket NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore. Di Package Manager Console (PMC), masukkan perintah berikut untuk menambahkan paket NuGet:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer

Paket Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet menyediakan middleware ASP.NET Core untuk EF Core halaman kesalahan. Middleware ini membantu mendeteksi dan mendiagnosis kesalahan dengan EF Core migrasi.

Untuk informasi tentang penyedia database lain yang tersedia untuk EF Core, lihat Penyedia database.

Membuat model data

Kelas entitas berikut dibuat untuk aplikasi ini:

Course-Enrollment-Student data model diagram

Entitas sebelumnya memiliki hubungan berikut:

  • Hubungan satu-ke-banyak antara Student entitas dan Enrollment . Siswa dapat didaftarkan dalam sejumlah kursus.
  • Hubungan satu-ke-banyak antara Course entitas dan Enrollment . Kursus dapat memiliki sejumlah siswa yang terdaftar di dalamnya.

Di bagian berikut, kelas dibuat untuk setiap entitas ini.

Entitas Siswa

Student entity diagram

Di folder Model, buat Student kelas dengan kode berikut:

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

Properti ID adalah kolom kunci primer (PK) dari tabel database yang sesuai dengan kelas ini. Secara default, EF menginterpretasikan properti yang dinamai ID atau classnameID sebagai kunci utama. Misalnya, PK dapat diberi nama StudentID daripada ID.

Properti Enrollments adalah properti navigasi. Properti navigasi menyimpan entitas lain yang terkait dengan entitas ini. Properti EnrollmentsStudent entitas:

  • Berisi semua entitas yang terkait dengan Student entitas tersebutEnrollment.
  • Jika baris tertentu Student dalam database memiliki dua baris terkait Enrollment :
    • Student Properti navigasi entitas tersebut Enrollments berisi kedua Enrollment entitas tersebut.

Enrollment baris berisi nilai PK siswa di StudentID kolom kunci asing (FK).

Jika properti navigasi dapat menampung beberapa entitas:

  • Jenis harus berupa daftar, seperti ICollection<T>, , List<T>atau HashSet<T>.
  • Entitas dapat ditambahkan, dihapus, dan diperbarui.

Hubungan navigasi banyak ke banyak dan satu ke banyak dapat berisi beberapa entitas. Saat ICollection<T> digunakan, EF membuat HashSet<T> koleksi secara default.

Entitas Pendaftaran

Enrollment entity diagram

Di folder Model, buat Enrollment kelas dengan kode berikut:

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

Properti EnrollmentID adalah PK. Entitas ini menggunakan pola alih-alih ID dengan sendirinyaclassnameID. Entitas Student menggunakan ID pola . Beberapa pengembang lebih suka menggunakan satu pola di seluruh model data. Dalam tutorial ini, variasi menggambarkan bahwa salah satu pola dapat digunakan. Tutorial selanjutnya menunjukkan cara menggunakan ID tanpa nama kelas membuatnya lebih mudah untuk menerapkan pewarisan dalam model data.

Properti Grade adalah enum. Setelah ?Grade deklarasi jenis menunjukkan bahwa Grade properti dapat diubah ke null. Nilai yang null berbeda dari nilai nol. null berarti nilai belum diketahui atau belum ditetapkan.

Properti StudentID adalah kunci asing (FK), dan properti navigasi yang sesuai adalah Student. Entitas Enrollment dikaitkan dengan satu Student entitas, sehingga properti hanya dapat menampung satu Student entitas. Ini berbeda dari Student.Enrollments properti navigasi, yang dapat menampung beberapa Enrollment entitas.

Properti CourseID adalah FK, dan properti navigasi yang sesuai adalah Course. Entitas Enrollment dikaitkan dengan satu Course entitas.

Entity Framework menginterpretasikan properti sebagai properti FK jika <bernama nama properti navigasi nama><> properti kunci utama. Misalnya, StudentID untuk Student properti navigasi karena Student PK entitas adalah ID. Properti FK juga dapat diberi nama <>properti kunci primer. Misalnya, CourseID karena Course PK entitas adalah CourseID.

Entitas Kursus

Course entity diagram

Di folder Model, buat Course kelas dengan kode berikut:

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

Properti Enrollments adalah properti navigasi. Entitas Course dapat terkait dengan sejumlah Enrollment entitas.

Atribut DatabaseGenerated dijelaskan dalam tutorial selanjutnya. Atribut ini memungkinkan memasukkan PK untuk kursus daripada membuat database.

Membuat konteks database

Kelas utama yang mengoordinasikan fungsionalitas EF untuk model data tertentu adalah DbContext kelas konteks database. Kelas ini dibuat dengan turunan Microsoft.EntityFrameworkCore.DbContext dari kelas . Kelas DbContext turunan menentukan entitas mana yang disertakan dalam model data. Beberapa perilaku EF dapat disesuaikan. Dalam proyek ini, kelas diberi nama SchoolContext.

Di folder proyek, buat folder bernama Data.

Di folder Data buat SchoolContext kelas dengan kode berikut:

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

Kode sebelumnya membuat DbSet properti untuk setiap set entitas. Dalam terminologi EF:

  • Kumpulan entitas biasanya sesuai dengan tabel database.
  • Entitas sesuai dengan baris dalam tabel.

Pernyataan DbSet<Enrollment> dan DbSet<Course> dapat dihilangkan dan akan berfungsi sama. EF akan menyertakannya secara implisit karena:

  • Entitas Student mereferensikan Enrollment entitas.
  • Entitas Enrollment mereferensikan Course entitas.

Saat database dibuat, EF membuat tabel yang memiliki nama sama dengan DbSet nama properti. Nama properti untuk koleksi biasanya jamak. Misalnya, Students daripada Student. Pengembang tidak setuju tentang apakah nama tabel harus di-pluralisasi atau tidak. Untuk tutorial ini, perilaku default ditimpa dengan menentukan nama tabel tunggal di DbContext. Untuk melakukannya, tambahkan kode yang disorot berikut setelah properti DbSet terakhir.

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

Daftarkan SchoolContext

ASP.NET Core mencakup injeksi dependensi. Layanan, seperti konteks database EF, terdaftar dengan injeksi dependensi selama pengaktifan aplikasi. Komponen yang memerlukan layanan ini, seperti pengontrol MVC, disediakan layanan ini melalui parameter konstruktor. Kode konstruktor pengontrol yang mendapatkan instans konteks ditampilkan nanti dalam tutorial ini.

Untuk mendaftar SchoolContext sebagai layanan, buka Startup.cs, dan tambahkan baris yang disorot ke ConfigureServices metode .

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

Nama string koneksi diteruskan ke konteks dengan memanggil metode pada DbContextOptionsBuilder objek. Untuk pengembangan lokal, sistem konfigurasi ASP.NET Core membaca string koneksi dari appsettings.json file.

appsettings.json Buka file dan tambahkan string koneksi seperti yang diperlihatkan dalam markup berikut:

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

Menambahkan filter pengecualian database

Tambahkan AddDatabaseDeveloperPageExceptionFilter ke ConfigureServices seperti yang ditunjukkan dalam kode berikut:

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

    services.AddDatabaseDeveloperPageExceptionFilter();

    services.AddControllersWithViews();
}

AddDatabaseDeveloperPageExceptionFilter menyediakan informasi kesalahan yang bermanfaat di lingkungan pengembangan.

LocalDB SQL Server Express

string koneksi menentukan SQL Server LocalDB. LocalDB adalah versi ringan dari SQL Server Express Database Engine dan ditujukan untuk pengembangan aplikasi, bukan penggunaan produksi. LocalDB dimulai sesuai permintaan dan berjalan dalam mode pengguna, sehingga tidak ada konfigurasi yang kompleks. Secara default, LocalDB membuat file DB .mdf di C:/Users/<user> direktori.

Menginisialisasi DB dengan data pengujian

EF membuat database kosong. Di bagian ini, metode ditambahkan yang dipanggil setelah database dibuat untuk mengisinya dengan data pengujian.

Metode EnsureCreated ini digunakan untuk membuat database secara otomatis. Dalam tutorial selanjutnya, Anda akan melihat cara menangani perubahan model dengan menggunakan Migrasi Pertama Kode untuk mengubah skema database alih-alih menghilangkan dan membuat ulang database.

Di folder Data, buat kelas baru bernama DbInitializer dengan kode berikut:

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

Kode sebelumnya memeriksa apakah database ada:

  • Jika database tidak ditemukan;
    • Ini dibuat dan dimuat dengan data pengujian. Ini memuat data pengujian ke dalam array daripada List<T> koleksi untuk mengoptimalkan performa.
  • Jika database ditemukan, tidak perlu tindakan apa pun.

Perbarui Program.cs dengan kode berikut:

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 lakukan hal berikut pada pengaktifan aplikasi:

  • Dapatkan instans konteks database dari kontainer injeksi dependensi.
  • Panggil DbInitializer.Initialize metode.
  • Buang konteks saat metode selesai seperti yang Initialize ditunjukkan dalam kode berikut:
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();
}

Saat pertama kali aplikasi dijalankan, database dibuat dan dimuat dengan data pengujian. Setiap kali model data berubah:

  • Menghapus database.
  • Perbarui metode seed, dan mulai afresh dengan database baru.

Dalam tutorial selanjutnya, database dimodifikasi ketika model data berubah, tanpa menghapus dan membuatnya kembali. Tidak ada data yang hilang saat model data berubah.

Membuat pengontrol dan tampilan

Gunakan mesin perancah di Visual Studio untuk menambahkan pengontrol dan tampilan MVC yang akan menggunakan EF untuk mengkueri dan menyimpan data.

Pembuatan otomatis metode dan tampilan tindakan CRUD dikenal sebagai perancah.

  • Di Penjelajah Solusi, klik Controllers kanan folder dan pilih Tambahkan > Item Perancah Baru.
  • Dalam kotak dialog Tambahkan Perancah :
    • Pilih Pengontrol MVC dengan tampilan, menggunakan Kerangka Kerja Entitas.
    • Klik Tambahkan. Kotak dialog Tambahkan Pengontrol MVC dengan tampilan, menggunakan Kerangka Kerja Entitas muncul: Scaffold Student
    • Di Kelas model, pilih Siswa.
    • Di Kelas konteks data, pilih SchoolContext.
    • Terima StudentsController default sebagai nama.
    • Klik Tambahkan.

Mesin perancah Visual Studio membuat StudentsController.cs file dan sekumpulan tampilan (*.cshtml file) yang berfungsi dengan pengontrol.

Perhatikan pengontrol mengambil SchoolContext sebagai parameter konstruktor.

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

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

ASP.NET Injeksi dependensi inti mengurus meneruskan instans SchoolContext ke pengontrol. Anda mengonfigurasinya di Startup kelas .

Pengontrol berisi Index metode tindakan, yang menampilkan semua siswa dalam database. Metode ini mendapatkan daftar siswa dari entitas Siswa yang ditetapkan dengan membaca Students properti instans konteks database:

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

Elemen pemrograman asinkron dalam kode ini dijelaskan kemudian dalam tutorial.

Tampilan Views/Students/Index.cshtml menampilkan daftar ini dalam tabel:

@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>

Tekan CTRL+F5 untuk menjalankan proyek atau pilih Debug > Mulai Tanpa Debugging dari menu.

Klik tab Siswa untuk melihat data pengujian yang DbInitializer.Initialize disisipkan metode. Bergantung pada seberapa sempit jendela browser Anda, Anda akan melihat Students tautan tab di bagian atas halaman atau Anda harus mengklik ikon navigasi di sudut kanan atas untuk melihat tautan.

Contoso University home page narrow

Students Index page

Menampilkan database

Saat aplikasi dimulai, DbInitializer.Initialize metode memanggil EnsureCreated. EF melihat bahwa tidak ada database:

  • Jadi itu membuat database.
  • Kode Initialize metode mengisi database dengan data.

Gunakan SQL Server Object Explorer (SSOX) untuk menampilkan database di Visual Studio:

  • Pilih SQL Server Object Explorer dari menu Tampilan di Visual Studio.
  • Di SSOX, pilih (localdb)\MSSQLLocalDB > Databases.
  • Pilih ContosoUniversity1, entri untuk nama database yang ada di string koneksi dalam appsettings.json file.
  • Perluas simpul Tabel untuk melihat tabel dalam database.

Tables in SSOX

Klik kanan tabel Siswa dan klik Tampilkan Data untuk melihat data dalam tabel.

Student table in SSOX

File *.mdf database dan *.ldf berada di folder C:\Users\<username> .

Karena EnsureCreated dipanggil dalam metode penginisialisasi yang berjalan pada awal aplikasi, Anda dapat:

  • Buat perubahan pada Student kelas .
  • Menghapus database.
  • Hentikan, lalu mulai aplikasi. Database secara otomatis dibuat ulang agar sesuai dengan perubahan.

Misalnya, jika EmailAddress properti ditambahkan ke Student kelas , kolom baru EmailAddress dalam tabel yang dibuat ulang. Tampilan tidak akan menampilkan properti baru EmailAddress .

Konvensi

Jumlah kode yang ditulis agar EF membuat database lengkap minimal karena penggunaan konvensi yang digunakan EF:

  • Nama DbSet properti digunakan sebagai nama tabel. Untuk entitas yang DbSet tidak dirujuk oleh properti, nama kelas entitas digunakan sebagai nama tabel.
  • Nama properti entitas digunakan untuk nama kolom.
  • Properti entitas yang diberi nama ID atau classnameID dikenali sebagai properti PK.
  • Properti ditafsirkan sebagai properti FK jika <bernama nama properti navigasi nama><> properti PK. Misalnya, StudentID untuk Student properti navigasi karena Student PK entitas adalah ID. Properti FK juga dapat diberi nama <>properti kunci primer. Misalnya, EnrollmentID karena Enrollment PK entitas adalah EnrollmentID.

Perilaku konvensional dapat ditimpa. Misalnya, nama tabel dapat ditentukan secara eksplisit, seperti yang ditunjukkan sebelumnya dalam tutorial ini. Nama kolom dan properti apa pun dapat diatur sebagai PK atau FK.

Kode asinkron

Pemrograman asinkron adalah mode default untuk ASP.NET Core dan EF Core.

Server web memiliki jumlah utas terbatas yang tersedia, dan dalam situasi beban tinggi semua utas yang tersedia mungkin digunakan. Ketika itu terjadi, server tidak dapat memproses permintaan baru sampai utas dikosongkan. Dengan kode sinkron, banyak utas mungkin diikat sementara mereka tidak benar-benar melakukan pekerjaan apa pun karena mereka menunggu I/O selesai. Dengan kode asinkron, ketika proses menunggu I/O selesai, utasnya dibebaskan untuk digunakan server untuk memproses permintaan lain. Akibatnya, kode asinkron memungkinkan sumber daya server digunakan lebih efisien, dan server diaktifkan untuk menangani lebih banyak lalu lintas tanpa penundaan.

Kode asinkron memang memperkenalkan sejumlah kecil overhead pada waktu proses, tetapi untuk situasi lalu lintas rendah, hit performa dapat diabaikan, sementara untuk situasi lalu lintas yang tinggi, potensi peningkatan performa sangat substansial.

Dalam kode berikut, async, Task<T>, await, dan ToListAsync buat kode dijalankan secara asinkron.

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}
  • Kata async kunci memberi tahu pengkompilasi untuk menghasilkan panggilan balik untuk bagian isi metode dan untuk secara otomatis membuat Task<IActionResult> objek yang dikembalikan.
  • Jenis Task<IActionResult> pengembalian mewakili pekerjaan yang sedang berlangsung dengan hasil jenis IActionResult.
  • Kata await kunci menyebabkan pengkompilasi membagi metode menjadi dua bagian. Bagian pertama berakhir dengan operasi yang dimulai secara asinkron. Bagian kedua dimasukkan ke dalam metode panggilan balik yang dipanggil ketika operasi selesai.
  • ToListAsync adalah versi asinkron dari ToList metode ekstensi.

Beberapa hal yang perlu diperhatikan saat menulis kode asinkron yang menggunakan EF:

  • Hanya pernyataan yang menyebabkan kueri atau perintah dikirim ke database yang dijalankan secara asinkron. Itu termasuk, misalnya, ToListAsync, , SingleOrDefaultAsyncdan SaveChangesAsync. Ini tidak termasuk, misalnya, pernyataan yang hanya mengubah IQueryable, seperti var students = context.Students.Where(s => s.LastName == "Davolio").
  • Konteks EF tidak aman untuk utas: jangan mencoba melakukan beberapa operasi secara paralel. Saat Anda memanggil metode EF asinkron apa pun, selalu gunakan await kata kunci.
  • Untuk memanfaatkan manfaat performa kode asinkron, pastikan bahwa setiap paket pustaka yang digunakan juga menggunakan asinkron jika mereka memanggil metode EF yang menyebabkan kueri dikirim ke database.

Untuk informasi selengkapnya tentang pemrograman asinkron di .NET, lihat Gambaran Umum Asinkron.

Batasi entitas yang diambil

Lihat Pertimbangan performa untuk informasi tentang membatasi jumlah entitas yang dikembalikan dari kueri.

Pengelogan SQL Core Kerangka Kerja Entitas

Konfigurasi pengelogan biasanya disediakan oleh bagian Logging dari file appsettings.{Environment}.json. Untuk mencatat pernyataan SQL, tambahkan "Microsoft.EntityFrameworkCore.Database.Command": "Information" ke appsettings.Development.json file:

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

Dengan ON sebelumnya JS, pernyataan SQL ditampilkan pada baris perintah dan di jendela output Visual Studio.

Untuk informasi selengkapnya, lihat Pengelogan di .NET Core dan ASP.NET Core dan masalah GitHub ini.

Lanjutkan ke tutorial berikutnya untuk mempelajari cara melakukan operasi CRUD dasar (membuat, membaca, memperbarui, menghapus).

Tutorial ini mengajarkan ASP.NET Core MVC dan Entity Framework Core dengan pengontrol dan tampilan. Razor Pages adalah model pemrograman alternatif. Untuk pengembangan baru, kami menyarankan Razor Pages melalui MVC dengan pengontrol dan tampilan. Lihat versi Razor Pages dari tutorial ini. Setiap tutorial mencakup beberapa materi yang tidak dicakup oleh tutorial lainnya:

Beberapa hal yang dimiliki tutorial MVC ini yang tidak dimiliki tutorial Razor Pages:

  • Mengimplementasikan pewarisan dalam model data
  • Melakukan kueri SQL mentah
  • Menggunakan LINQ dinamis untuk menyederhanakan kode

Beberapa hal yang dimiliki tutorial Razor Pages yang tidak dimiliki tutorial ini:

  • Menggunakan metode Pilih untuk memuat data terkait
  • Praktik terbaik untuk EF.

Aplikasi web sampel Contoso University menunjukkan cara membuat aplikasi web MVC ASP.NET Core 2.2 menggunakan Entity Framework (EF) Core 2.2 dan Visual Studio 2019.

Tutorial ini belum diperbarui untuk ASP.NET Core 3.1. Ini telah diperbarui untuk ASP.NET Core 5.0.

Aplikasi sampel adalah situs web untuk Universitas Contoso fiktif. Ini termasuk fungsionalitas seperti penerimaan siswa, pembuatan kursus, dan tugas instruktur. Ini adalah yang pertama dalam serangkaian tutorial yang menjelaskan cara membangun aplikasi sampel Contoso University dari awal.

Prasyarat

Pemecahan Masalah

Jika Anda mengalami masalah yang tidak dapat Anda atasi, Anda umumnya dapat menemukan solusi dengan membandingkan kode Anda dengan proyek yang telah selesai. Untuk daftar kesalahan umum dan cara menyelesaikannya, lihat bagian Pemecahan Masalah dari tutorial terakhir dalam seri. Jika Anda tidak menemukan apa yang Anda butuhkan di sana, Anda dapat memposting pertanyaan ke StackOverflow.com untuk ASP.NET Core atau EF Core.

Tip

Ini adalah serangkaian tutorial 10, yang masing-masing dibangun berdasarkan apa yang dilakukan dalam tutorial sebelumnya. Pertimbangkan untuk menyimpan salinan proyek setelah setiap penyelesaian tutorial berhasil. Kemudian jika Anda mengalami masalah, Anda dapat memulai kembali dari tutorial sebelumnya alih-alih kembali ke awal seluruh seri.

Aplikasi web Contoso University

Aplikasi yang akan Anda bangun dalam tutorial ini adalah situs web universitas sederhana.

Pengguna dapat melihat dan memperbarui informasi siswa, kursus, dan instruktur. Berikut adalah beberapa layar yang akan Anda buat.

Students Index page

Students Edit page

Membuat aplikasi web

  • Buka Visual Studio.

  • Dari menu File, pilih Proyek Baru>.

  • Dari panel kiri, pilih Web Visual C# > Terinstal>.

  • Pilih templat proyek ASP.NET Core Web Application .

  • Masukkan ContosoUniversity sebagai nama dan klik OK.

    New Project dialog

  • Tunggu hingga dialog Aplikasi Web New ASP.NET Core muncul.

  • Pilih .NET Core, ASP.NET Core 2.2 dan templat Aplikasi Web (Model-View-Controller).

  • Pastikan Otentikasi diatur ke Tanpa Otentikasi.

  • Pilih OK

    New ASP.NET Core Project dialog

Menyiapkan gaya situs

Beberapa perubahan sederhana akan menyiapkan menu situs, tata letak, dan beranda.

Buka Views/Shared/_Layout.cshtml dan buat perubahan berikut:

  • Ubah setiap kemunculan "ContosoUniversity" menjadi "Contoso University". Ada tiga kejadian.

  • Tambahkan entri menu untuk Tentang, Siswa, Kursus, Instruktur, dan Departemen, dan hapus Privacy entri menu.

Perubahan disorot.

<!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">
            &copy; 2019 - Contoso University - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.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>

Di Views/Home/Index.cshtml, ganti konten file dengan kode berikut untuk mengganti teks tentang ASP.NET dan MVC dengan teks tentang aplikasi ini:

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

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

Tekan CTRL+F5 untuk menjalankan proyek atau pilih Debug > Mulai Tanpa Debugging dari menu. Anda melihat beranda dengan tab untuk halaman yang akan Anda buat dalam tutorial ini.

Contoso University home page

Tentang EF Core paket NuGet

Untuk menambahkan EF Core dukungan ke proyek, instal penyedia database yang ingin Anda targetkan. Tutorial ini menggunakan SQL Server, dan paket penyedianya adalah Microsoft.EntityFrameworkCore.SqlServer. Paket ini disertakan dalam Microsoft.AspNetCore.App metapackage, jadi Anda tidak perlu mereferensikan paket.

Paket EF SQL Server dan dependensinya (Microsoft.EntityFrameworkCore dan Microsoft.EntityFrameworkCore.Relational) menyediakan dukungan runtime untuk EF. Anda akan menambahkan paket alat nanti, dalam tutorial Migrasi .

Untuk informasi tentang penyedia database lain yang tersedia untuk Entity Framework Core, lihat Penyedia database.

Membuat model data

Selanjutnya Anda akan membuat kelas entitas untuk aplikasi Contoso University. Anda akan mulai dengan tiga entitas berikut.

Course-Enrollment-Student data model diagram

Ada hubungan satu-ke-banyak antara StudentEnrollment dan entitas, dan ada hubungan satu-ke-banyak antara Course dan Enrollment entitas. Dengan kata lain, siswa dapat terdaftar di sejumlah kursus, dan kursus dapat memiliki sejumlah siswa yang terdaftar di dalamnya.

Di bagian berikut, Anda akan membuat kelas untuk masing-masing entitas ini.

Entitas Siswa

Student entity diagram

Di folder Model, buat file kelas bernama Student.cs dan ganti kode templat dengan kode berikut.

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

Properti ID akan menjadi kolom kunci utama tabel database yang sesuai dengan kelas ini. Secara default, Kerangka Kerja Entitas menginterpretasikan properti yang dinamai ID atau classnameID sebagai kunci utama.

Properti Enrollments adalah properti navigasi. Properti navigasi menyimpan entitas lain yang terkait dengan entitas ini. Dalam hal ini, Enrollments properti dari Student entity akan menampung semua entitas yang terkait dengan Student entitas tersebutEnrollment. Dengan kata lain, jika Student baris dalam database memiliki dua baris terkait Enrollment (baris yang berisi nilai kunci utama siswa di kolom kunci asing StudentID mereka), Student properti navigasi entitas tersebut Enrollments akan berisi dua Enrollment entitas tersebut.

Jika properti navigasi dapat menampung beberapa entitas (seperti dalam hubungan banyak ke banyak atau satu-ke-banyak), jenisnya harus berupa daftar di mana entri dapat ditambahkan, dihapus, dan diperbarui, seperti ICollection<T>. Anda dapat menentukan ICollection<T> atau jenis seperti List<T> atau HashSet<T>. Jika Anda menentukan ICollection<T>, EF membuat HashSet<T> koleksi secara default.

Entitas Pendaftaran

Enrollment entity diagram

Di folder Model, buat Enrollment.cs dan ganti kode yang ada dengan kode berikut:

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

Properti EnrollmentID akan menjadi kunci utama; entitas ini menggunakan pola alih-alih classnameIDID dengan sendirinya Student seperti yang Anda lihat di entitas. Biasanya Anda akan memilih satu pola dan menggunakannya di seluruh model data Anda. Di sini, variasi menggambarkan bahwa Anda dapat menggunakan salah satu pola. Dalam tutorial selanjutnya, Anda akan melihat cara menggunakan ID tanpa nama kelas membuatnya lebih mudah untuk menerapkan pewarisan dalam model data.

Properti Grade adalah enum. Tanda tanya setelah Grade deklarasi jenis menunjukkan bahwa Grade properti dapat diubah ke null. Nilai null berbeda dari nilai nol -- null berarti nilai belum diketahui atau belum ditetapkan.

Properti StudentID adalah kunci asing, dan properti navigasi yang sesuai adalah Student. Entitas Enrollment dikaitkan dengan satu Student entitas, sehingga properti hanya dapat menampung satu Student entitas (tidak seperti Student.Enrollments properti navigasi yang Anda lihat sebelumnya, yang dapat menampung beberapa Enrollment entitas).

Properti CourseID adalah kunci asing, dan properti navigasi yang sesuai adalah Course. Entitas Enrollment dikaitkan dengan satu Course entitas.

Entity Framework menginterpretasikan properti sebagai properti kunci asing jika dinamai <navigation property name><primary key property name> (misalnya, StudentID untuk Student properti navigasi karena Student kunci utama entitas adalah ID). Properti kunci asing juga dapat diberi nama sederhana <primary key property name> (misalnya, CourseIDCourse karena kunci utama entitas adalah CourseID).

Entitas Kursus

Course entity diagram

Di folder Model, buat Course.cs dan ganti kode yang ada dengan kode berikut:

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

Properti Enrollments adalah properti navigasi. Entitas Course dapat terkait dengan sejumlah Enrollment entitas.

Kita akan mengatakan lebih lanjut DatabaseGenerated tentang atribut dalam tutorial selanjutnya dalam seri ini. Pada dasarnya, atribut ini memungkinkan Anda memasukkan kunci utama untuk kursus daripada membuat database.

Membuat konteks database

Kelas utama yang mengoordinasikan fungsionalitas Kerangka Kerja Entitas untuk model data tertentu adalah kelas konteks database. Anda membuat kelas ini dengan turunan Microsoft.EntityFrameworkCore.DbContext dari kelas . Dalam kode Anda, Anda menentukan entitas mana yang disertakan dalam model data. Anda juga dapat menyesuaikan perilaku Kerangka Kerja Entitas tertentu. Dalam proyek ini, kelas diberi nama SchoolContext.

Di folder proyek, buat folder bernama Data.

Di folder Data buat file kelas baru bernama SchoolContext.cs, dan ganti kode templat dengan kode berikut:

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

Kode ini membuat DbSet properti untuk setiap set entitas. Dalam terminologi Kerangka Kerja Entitas, kumpulan entitas biasanya sesuai dengan tabel database, dan entitas sesuai dengan baris dalam tabel.

Anda bisa menghilangkan DbSet<Enrollment> pernyataan dan DbSet<Course> dan itu akan bekerja sama. Kerangka Kerja Entitas akan menyertakannya secara implisit karena Student entitas mereferensikan Enrollment entitas dan entitas mereferensikan CourseEnrollment entitas.

Saat database dibuat, EF membuat tabel yang memiliki nama sama dengan DbSet nama properti. Nama properti untuk koleksi biasanya jamak (Siswa daripada Siswa), tetapi pengembang tidak setuju tentang apakah nama tabel harus di-pluralisasi atau tidak. Untuk tutorial ini, Anda akan mengambil alih perilaku default dengan menentukan nama tabel tunggal di DbContext. Untuk melakukannya, tambahkan kode yang disorot berikut setelah properti DbSet terakhir.

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

Buat proyek sebagai pemeriksaan kesalahan pengkompilasi.

Mendaftarkan SchoolContext

ASP.NET Core menerapkan injeksi dependensi secara default. Layanan (seperti konteks database EF) terdaftar dengan injeksi dependensi selama startup aplikasi. Komponen yang memerlukan layanan ini (seperti pengontrol MVC) disediakan layanan ini melalui parameter konstruktor. Anda akan melihat kode konstruktor pengontrol yang mendapatkan instans konteks nanti dalam tutorial ini.

Untuk mendaftar SchoolContext sebagai layanan, buka Startup.cs, dan tambahkan baris yang disorot ke ConfigureServices metode .

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

Nama string koneksi diteruskan ke konteks dengan memanggil metode pada DbContextOptionsBuilder objek. Untuk pengembangan lokal, sistem konfigurasi ASP.NET Core membaca string koneksi dari appsettings.json file.

Tambahkan using pernyataan untuk ContosoUniversity.Data dan Microsoft.EntityFrameworkCore namespace, lalu buat proyek.

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

appsettings.json Buka file dan tambahkan string koneksi seperti yang diperlihatkan dalam contoh berikut.

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

LocalDB SQL Server Express

string koneksi menentukan database SQL Server LocalDB. LocalDB adalah versi ringan dari SQL Server Express Database Engine dan ditujukan untuk pengembangan aplikasi, bukan penggunaan produksi. LocalDB dimulai sesuai permintaan dan berjalan dalam mode pengguna, sehingga tidak ada konfigurasi yang kompleks. Secara default, LocalDB membuat file database .mdf di C:/Users/<user> direktori.

Menginisialisasi DB dengan data pengujian

Kerangka Kerja Entitas akan membuat database kosong untuk Anda. Di bagian ini, Anda menulis metode yang dipanggil setelah database dibuat untuk mengisinya dengan data pengujian.

Di sini Anda akan menggunakan EnsureCreated metode untuk membuat database secara otomatis. Dalam tutorial selanjutnya, Anda akan melihat cara menangani perubahan model dengan menggunakan Migrasi Pertama Kode untuk mengubah skema database alih-alih menghilangkan dan membuat ulang database.

Di folder Data, buat file kelas baru bernama DbInitializer.cs dan ganti kode templat dengan kode berikut, yang menyebabkan database dibuat saat diperlukan dan memuat data pengujian ke database baru.

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

Kode memeriksa apakah ada siswa dalam database, dan jika tidak, ia mengasumsikan database baru dan perlu disemai dengan data pengujian. Ini memuat data pengujian ke dalam array daripada List<T> koleksi untuk mengoptimalkan performa.

Di Program.cs, ubah Main metode untuk melakukan hal berikut pada startup aplikasi:

  • Dapatkan instans konteks database dari kontainer injeksi dependensi.
  • Panggil metode benih, teruskan konteksnya.
  • Buang konteks ketika metode benih dilakukan.
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>();
                });
    }
}

Pertama kali Anda menjalankan aplikasi, database akan dibuat dan disemai dengan data pengujian. Setiap kali Anda mengubah model data:

  • Menghapus database.
  • Perbarui metode seed, dan mulai afresh dengan database baru dengan cara yang sama.

Dalam tutorial selanjutnya, Anda akan melihat cara memodifikasi database saat model data berubah, tanpa menghapus dan membuatnya kembali.

Membuat pengontrol dan tampilan

Di bagian ini, mesin perancah di Visual Studio digunakan untuk menambahkan pengontrol dan tampilan MVC yang akan menggunakan EF untuk mengkueri dan menyimpan data.

Pembuatan otomatis metode dan tampilan tindakan CRUD dikenal sebagai perancah. Perancah berbeda dari pembuatan kode karena kode perancah adalah titik awal yang dapat Anda ubah agar sesuai dengan kebutuhan Anda sendiri, sedangkan Anda biasanya tidak memodifikasi kode yang dihasilkan. Ketika Anda perlu menyesuaikan kode yang dihasilkan, Anda menggunakan kelas parsial atau Anda meregenerasi kode saat hal-hal berubah.

  • Klik kanan folder Pengontrol di Penjelajah Solusi dan pilih Tambahkan > Item Perancah Baru.
  • Dalam kotak dialog Tambahkan Perancah :
    • Pilih Pengontrol MVC dengan tampilan, menggunakan Kerangka Kerja Entitas.
    • Klik Tambahkan. Kotak dialog Tambahkan Pengontrol MVC dengan tampilan, menggunakan Kerangka Kerja Entitas muncul: Scaffold Student
    • Di Kelas model pilih Siswa.
    • Di Kelas konteks data pilih SchoolContext.
    • Terima StudentsController default sebagai nama.
    • Klik Tambahkan.

Mesin perancah Visual Studio membuat StudentsController.cs file dan sekumpulan tampilan (.cshtml file) yang berfungsi dengan pengontrol.

Perhatikan pengontrol mengambil SchoolContext sebagai parameter konstruktor.

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

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

ASP.NET Injeksi dependensi inti mengurus meneruskan instans SchoolContext ke pengontrol. Itu dikonfigurasi dalam Startup.cs file.

Pengontrol berisi Index metode tindakan, yang menampilkan semua siswa dalam database. Metode ini mendapatkan daftar siswa dari entitas Siswa yang ditetapkan dengan membaca Students properti instans konteks database:

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

Anda mempelajari tentang elemen pemrograman asinkron dalam kode ini nanti dalam tutorial.

Tampilan Views/Students/Index.cshtml menampilkan daftar ini dalam tabel:

@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>

Tekan CTRL+F5 untuk menjalankan proyek atau pilih Debug > Mulai Tanpa Debugging dari menu.

Klik tab Siswa untuk melihat data pengujian yang DbInitializer.Initialize disisipkan metode. Bergantung pada seberapa sempit jendela browser Anda, Anda akan melihat Students tautan tab di bagian atas halaman atau Anda harus mengklik ikon navigasi di sudut kanan atas untuk melihat tautan.

Contoso University home page narrow

Students Index page

Menampilkan database

Saat Anda memulai aplikasi, metode memanggil DbInitializer.InitializeEnsureCreated. EF melihat bahwa tidak ada database dan sehingga membuat database, maka Initialize sisa kode metode mengisi database dengan data. Anda dapat menggunakan SQL Server Object Explorer (SSOX) untuk melihat database di Visual Studio.

Tutup browser.

Jika jendela SSOX belum terbuka, pilih dari menu Tampilan di Visual Studio.

Di SSOX, klik (localdb)\MSSQLLocalDB > Databases, lalu klik entri untuk nama database yang ada di string koneksi dalam appsettings.json file.

Perluas simpul Tabel untuk melihat tabel dalam database.

Tables in SSOX

Klik kanan tabel Siswa dan klik Tampilkan Data untuk melihat kolom yang dibuat dan baris yang disisipkan ke dalam tabel.

Student table in SSOX

File database .mdf dan .ldf berada di folder C:\Users\<username> .

Karena Anda memanggil EnsureCreated metode inisialisasi yang berjalan pada awal aplikasi, Anda sekarang dapat membuat perubahan pada Student kelas, menghapus database, menjalankan aplikasi lagi, dan database akan secara otomatis dibuat ulang agar sesuai dengan perubahan Anda. Misalnya, jika Anda menambahkan EmailAddress properti ke Student kelas , Anda akan melihat kolom baru EmailAddress di tabel yang dibuat ulang.

Konvensi

Jumlah kode yang harus Anda tulis agar Kerangka Kerja Entitas dapat membuat database lengkap untuk Anda minimal karena penggunaan konvensi, atau asumsi yang dibuat Kerangka Kerja Entitas.

  • Nama DbSet properti digunakan sebagai nama tabel. Untuk entitas yang DbSet tidak dirujuk oleh properti, nama kelas entitas digunakan sebagai nama tabel.
  • Nama properti entitas digunakan untuk nama kolom.
  • Properti entitas yang diberi nama ID atau classnameID dikenali sebagai properti kunci utama.
  • Properti ditafsirkan sebagai properti kunci asing jika <bernama nama properti navigasi nama>>< properti kunci utama (misalnya, StudentID untuk Student properti navigasi karena Student kunci utama entitas adalah ).ID Properti kunci asing juga dapat diberi nama hanya <nama> properti kunci primer (misalnya, EnrollmentID karena Enrollment kunci utama entitas adalah EnrollmentID).

Perilaku konvensional dapat ditimpa. Misalnya, Anda dapat secara eksplisit menentukan nama tabel, seperti yang Anda lihat sebelumnya dalam tutorial ini. Dan Anda dapat mengatur nama kolom dan mengatur properti apa pun sebagai kunci primer atau kunci asing, seperti yang akan Anda lihat di tutorial selanjutnya dalam seri ini.

Kode asinkron

Pemrograman asinkron adalah mode default untuk ASP.NET Core dan EF Core.

Server web memiliki jumlah utas terbatas yang tersedia, dan dalam situasi beban tinggi semua utas yang tersedia mungkin digunakan. Ketika itu terjadi, server tidak dapat memproses permintaan baru sampai utas dikosongkan. Dengan kode sinkron, banyak utas mungkin diikat sementara mereka tidak benar-benar melakukan pekerjaan apa pun karena mereka menunggu I/O selesai. Dengan kode asinkron, ketika proses menunggu I/O selesai, utasnya dibebaskan untuk digunakan server untuk memproses permintaan lain. Akibatnya, kode asinkron memungkinkan sumber daya server digunakan lebih efisien, dan server diaktifkan untuk menangani lebih banyak lalu lintas tanpa penundaan.

Kode asinkron memang memperkenalkan sejumlah kecil overhead pada waktu proses, tetapi untuk situasi lalu lintas rendah, hit performa dapat diabaikan, sementara untuk situasi lalu lintas yang tinggi, potensi peningkatan performa sangat substansial.

Dalam kode berikut, async kata kunci, Task<T> nilai pengembalian, await kata kunci, dan ToListAsync metode membuat kode dijalankan secara asinkron.

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}
  • Kata async kunci memberi tahu pengkompilasi untuk menghasilkan panggilan balik untuk bagian isi metode dan untuk secara otomatis membuat Task<IActionResult> objek yang dikembalikan.
  • Jenis Task<IActionResult> pengembalian mewakili pekerjaan yang sedang berlangsung dengan hasil jenis IActionResult.
  • Kata await kunci menyebabkan pengkompilasi membagi metode menjadi dua bagian. Bagian pertama berakhir dengan operasi yang dimulai secara asinkron. Bagian kedua dimasukkan ke dalam metode panggilan balik yang dipanggil ketika operasi selesai.
  • ToListAsync adalah versi asinkron dari ToList metode ekstensi.

Beberapa hal yang perlu diperhatikan ketika Anda menulis kode asinkron yang menggunakan Kerangka Kerja Entitas:

  • Hanya pernyataan yang menyebabkan kueri atau perintah dikirim ke database yang dijalankan secara asinkron. Itu termasuk, misalnya, ToListAsync, , SingleOrDefaultAsyncdan SaveChangesAsync. Ini tidak termasuk, misalnya, pernyataan yang hanya mengubah IQueryable, seperti var students = context.Students.Where(s => s.LastName == "Davolio").
  • Konteks EF tidak aman untuk utas: jangan mencoba melakukan beberapa operasi secara paralel. Saat Anda memanggil metode EF asinkron apa pun, selalu gunakan await kata kunci.
  • Jika Anda ingin memanfaatkan manfaat performa kode asinkron, pastikan bahwa paket pustaka apa pun yang Anda gunakan (seperti untuk penomoran halaman), juga gunakan asinkron jika mereka memanggil metode Kerangka Kerja Entitas apa pun yang menyebabkan kueri dikirim ke database.

Untuk informasi selengkapnya tentang pemrograman asinkron di .NET, lihat Gambaran Umum Asinkron.

Langkah berikutnya

Lanjutkan ke tutorial berikutnya untuk mempelajari cara melakukan operasi CRUD dasar (membuat, membaca, memperbarui, menghapus).