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
- Jika Anda baru mengenal ASP.NET Core MVC, buka seri tutorial Mulai menggunakan ASP.NET Core MVC sebelum memulai yang ini.
- Visual Studio 2022 dengan beban kerja ASP.NET serta pengembangan web.
- .NET 6.0 SDK
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:
Membuat aplikasi web
- Mulai Visual Studio dan pilih Buat proyek baru.
- Dalam dialog Buat proyek baru, pilih ASP.NET Core Web Application>Next.
- Dalam dialog Konfigurasikan proyek baru Anda, masukkan
ContosoUniversity
untuk Nama proyek. Penting untuk menggunakan nama yang tepat ini termasuk kapitalisasi, sehingga setiapnamespace
kecocokan saat kode disalin. - Pilih Buat.
- Dalam dialog Buat aplikasi web ASP.NET Core baru, pilih:
- .NET Core dan ASP.NET Core 5.0 di menu dropdown.
- ASP.NET Core Web App (Model-View-Controller).
- Buat
Menyiapkan gaya situs
Beberapa perubahan dasar menyiapkan menu situs, tata letak, dan home halaman.
Buka Views/Shared/_Layout.cshtml
dan buat perubahan berikut:
- Ubah setiap kemunculan menjadi
ContosoUniversity
Contoso 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">
© 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 »</a></p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from GitHub.</p>
<p><a class="btn btn-default" href="https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/data/ef-mvc/intro/samples/5cu-final">See project source code »</a></p>
</div>
</div>
Tekan CTRL+F5 untuk menjalankan proyek atau pilih Debug > Mulai Tanpa Debugging dari menu. Halaman home ditampilkan dengan tab untuk halaman yang dibuat dalam tutorial ini.
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:
Entitas sebelumnya memiliki hubungan berikut:
- Hubungan satu-ke-banyak antara
Student
entitas danEnrollment
. Siswa dapat didaftarkan dalam sejumlah kursus. - Hubungan satu-ke-banyak antara
Course
entitas danEnrollment
. Kursus dapat memiliki sejumlah siswa yang terdaftar di dalamnya.
Di bagian berikut, kelas dibuat untuk setiap entitas ini.
Entitas Siswa
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 Enrollments
Student
entitas:
- Berisi semua entitas yang terkait dengan
Student
entitas tersebutEnrollment
. - Jika baris tertentu
Student
dalam database memiliki dua baris terkaitEnrollment
:Student
Properti navigasi entitas tersebutEnrollments
berisi keduaEnrollment
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>
atauHashSet<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
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
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
mereferensikanEnrollment
entitas. - Entitas
Enrollment
mereferensikanCourse
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.
- Ini dibuat dan dimuat dengan data pengujian. Ini memuat data pengujian ke dalam array daripada
- 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:
- 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.
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 dalamappsettings.json
file. - Perluas simpul Tabel untuk melihat tabel dalam database.
Klik kanan tabel Siswa dan klik Tampilkan Data untuk melihat data dalam tabel.
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 yangDbSet
tidak dirujuk oleh properti, nama kelas entitas digunakan sebagai nama tabel. - Nama properti entitas digunakan untuk nama kolom.
- Properti entitas yang diberi nama
ID
atauclassnameID
dikenali sebagai properti PK. - Properti ditafsirkan sebagai properti FK jika
<
bernama nama properti navigasi nama><
>
properti PK. Misalnya,StudentID
untukStudent
properti navigasi karenaStudent
PK entitas adalahID
. Properti FK juga dapat diberi nama<
>
properti kunci primer. Misalnya,EnrollmentID
karenaEnrollment
PK entitas adalahEnrollmentID
.
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 membuatTask<IActionResult>
objek yang dikembalikan. - Jenis
Task<IActionResult>
pengembalian mewakili pekerjaan yang sedang berlangsung dengan hasil jenisIActionResult
. - 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 dariToList
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
, ,SingleOrDefaultAsync
danSaveChangesAsync
. Ini tidak termasuk, misalnya, pernyataan yang hanya mengubahIQueryable
, sepertivar 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 JSON sebelumnya, 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
- .NET Core SDK 2.2
- Visual Studio 2019 dengan beban kerja berikut:
- ASP.NET dan beban kerja pengembangan web
- Beban kerja pengembangan lintas platform .NET Core
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.
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.
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
Menyiapkan gaya situs
Beberapa perubahan sederhana akan menyiapkan menu situs, tata letak, dan home halaman.
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">
© 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 »</a></p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from GitHub.</p>
<p><a class="btn btn-default" href="https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/data/ef-mvc/intro/samples/cu-final">See project source code »</a></p>
</div>
</div>
Tekan CTRL+F5 untuk menjalankan proyek atau pilih Debug > Mulai Tanpa Debugging dari menu. Anda melihat home halaman dengan tab untuk halaman yang akan Anda buat dalam tutorial ini.
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.
Ada hubungan satu-ke-banyak antara Student
Enrollment
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
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
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 classnameID
ID
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, CourseID
Course
karena kunci utama entitas adalah CourseID
).
Entitas Kursus
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 Course
Enrollment
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:
- 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.
Menampilkan database
Saat Anda memulai aplikasi, metode memanggil DbInitializer.Initialize
EnsureCreated
. 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.
Klik kanan tabel Siswa dan klik Tampilkan Data untuk melihat kolom yang dibuat dan baris yang disisipkan ke dalam tabel.
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 yangDbSet
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
untukStudent
properti navigasi karenaStudent
kunci utama entitas adalah ).ID
Properti kunci asing juga dapat diberi nama hanya <nama> properti kunci primer (misalnya,EnrollmentID
karenaEnrollment
kunci utama entitas adalahEnrollmentID
).
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 membuatTask<IActionResult>
objek yang dikembalikan. - Jenis
Task<IActionResult>
pengembalian mewakili pekerjaan yang sedang berlangsung dengan hasil jenisIActionResult
. - 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 dariToList
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
, ,SingleOrDefaultAsync
danSaveChangesAsync
. Ini tidak termasuk, misalnya, pernyataan yang hanya mengubahIQueryable
, sepertivar 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).
ASP.NET Core