实现学生与班级联表查询
准备工作
1、实体类:
新建 Model/StudentClass.cs 类
cs
public class StudentClass
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name ="班级名称")]
public string ClassName { get; set; }
}
修改 Model/Student.cs 类
cs
//追加如下字段 做外键
public int? StudentClassId { get; set; } // ?:让它可空 当原本数据库中有数据时添加新字段作为外键
[AllowNull]
[ForeignKey("StudentClassId")]
public virtual StudentClass? StudentClasses { get; set; }
2、修改 AppDbContext.cs 上下文

3、EF Core 迁移操作
cs
程序包管理器控制台 命令行:
Add-Migration + 迁移名称 ---作用:启动迁移并生成迁移的代码
Update-database ---作用:把操作更新到数据库
4、修改 _Layout.cshtml 布局页

5、添加班级相关页面

①、ClassPages/Index.cshtml
前端代码:
html
@page
@model RazorStudentManager.Pages.ClassPages.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a class="btn btn-primary w-25" asp-page="Create">创建</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.StudentClass[0].ClassName)
</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.StudentClass) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.ClassName)
</td>
<td>
<a class="btn btn-success btn-sm" asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
<a class="btn btn-secondary btn-sm" asp-page="./Details" asp-route-id="@item.Id">Details</a> |
<a class="btn btn-danger btn-sm" asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
后端代码:
cs
public class IndexModel : PageModel
{
private readonly RazorStudentManager.AppData.AppDbContext _context;
public IndexModel(RazorStudentManager.AppData.AppDbContext context)
{
_context = context;
}
public IList<StudentClass> StudentClass { get;set; } = default!;
public async Task OnGetAsync()
{
StudentClass = await _context.StudentClasses.ToListAsync();
}
}
实现效果

②、ClassPages/Create.cshtml
前端代码
html
@page
@model RazorStudentManager.Pages.ClassPages.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>StudentClass</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<span class="text-danger">*</span>
<label asp-for="StudentClass.ClassName" class="control-label"></label>
<input asp-for="StudentClass.ClassName" class="form-control" />
<span asp-validation-for="StudentClass.ClassName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
后端代码
cs
public class CreateModel : PageModel
{
private readonly RazorStudentManager.AppData.AppDbContext _context;
public CreateModel(RazorStudentManager.AppData.AppDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public StudentClass StudentClass { get; set; } = default!;
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.StudentClasses.Add(StudentClass);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
实现效果

③、ClassPages/Edit.cshtml
前端代码
html
@page
@model RazorStudentManager.Pages.ClassPages.EditModel
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>StudentClass</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="StudentClass.Id" />
<div class="form-group">
<span class="text-danger">*</span>
<label asp-for="StudentClass.ClassName" class="control-label"></label>
<input asp-for="StudentClass.ClassName" class="form-control" />
<span asp-validation-for="StudentClass.ClassName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
后端代码
cs
public class EditModel : PageModel
{
private readonly RazorStudentManager.AppData.AppDbContext _context;
public EditModel(RazorStudentManager.AppData.AppDbContext context)
{
_context = context;
}
[BindProperty]
public StudentClass StudentClass { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var studentclass = await _context.StudentClasses.FirstOrDefaultAsync(m => m.Id == id);
if (studentclass == null)
{
return NotFound();
}
StudentClass = studentclass;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more information, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(StudentClass).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!StudentClassExists(StudentClass.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool StudentClassExists(int id)
{
return _context.StudentClasses.Any(e => e.Id == id);
}
}
实现效果

实现联表查询
1、StudentPage/Index.cshtml
学生管理页 列表展示学生班级信息,搜索栏选择班级

前端代码:
html
@page
@model RazorStudentManager.Pages.StudentPage.IndexModel
<br />
<div class="row">
<h1 class="text-info col-4"> Student List </h1>
<div class="col-2 offset-6">
<a asp-page="Create" class="btn btn-primary form-control text-white">创建学生</a>
</div>
</div>
<div class=" container p-0 m-0 ">
<form method="get">
<div class="row">
<div class="col-4">
<select class="form-select" asp-for="ClassId" asp-items="Model.ClassList">
<option value="">请选择班级</option>
</select>
</div>
<div class="col-4 offset-4">
<div class="input-group">
<input class="form-control" asp-for="Search" placeholder="请输入姓名查询" />
<div class="input-group-append">
<button type="submit" class="btn btn-primary">查询</button>
</div>
</div>
</div>
</div>
</form>
<form method="post">
<table class="table m-2">
<thead class="table-light">
<tr>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Id"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Name"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().StudentClasses.ClassName"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Gender"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Age"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Phone"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Address"></label>
</th>
<th>
<label scope="col" asp-for="Students.FirstOrDefault().Description"></label>
</th>
<th>
<label scope="col"> 操作</label>
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Students)
{
<tr>
<th scope="row">@item.Id</th>
<td>@item.Name</td>
<td>@item.StudentClasses.ClassName</td>
<td>@item.Gender</td>
<td>@item.Age</td>
<td>@item.Phone</td>
<td>@item.Address</td>
<td>@item.Description</td>
<td>
<button asp-page-handler="Delete" asp-route-id="@item.Id" class="btn btn-danger btn-sm" onclick="return confirm('您确定要删除吗??')">删除</button>
<a asp-route-id="@item.Id" asp-page="Edit" class="btn btn-success btn-sm">修改</a>
</td>
</tr>
}
</tbody>
</table>
</form>
</div>
@{
}
后端代码:
cs
public class IndexModel : PageModel
{
private readonly AppDbContext _db;
public IndexModel(AppDbContext db)
{
_db = db;
}
//可枚举类型存放数据
public IEnumerable<Student> Students { get; set; }
[BindProperty(SupportsGet =true)] //绑定
public string Search { get; set; }
[BindProperty(SupportsGet = true)] //绑定
public int? ClassId { get; set; }
public SelectList ClassList { get; set; }
//获取数据
public async Task OnGet()
{
var items = await _db.StudentClasses.ToListAsync();
ClassList = new SelectList(items, "Id", "ClassName");
var query = _db.Students
.Include(c=>c.StudentClasses) //Include
.AsNoTracking(); //AsNoTracking方法不跟踪,提高查询效率
if (!string.IsNullOrEmpty(Search))
{
query = query.Where(s => s.Name.Contains(Search));
}
if (!string.IsNullOrEmpty(Search))
{
query = query.Where(s => s.Name.Contains(Search));
}
Students = await query.ToListAsync();
}
//删除
public async Task<IActionResult> OnPostDelete(int id)
{
var student = await _db.Students.FindAsync(id);
if (student == null)
{
return NotFound();
}
_db.Students.Remove(student); //将student状态设置删除
await _db.SaveChangesAsync();
return RedirectToPage();
}
}
2、StudentPage/Create.cshtml

前端代码:
html
@page
@model RazorStudentManager.Pages.StudentPage.CreateModel
<br />
<h1 class="text-info"> Create </h1>
<br />
<div class="border container p-4">
<form method="post" >
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.Name"></label>
</div>
<div class="col-6">
<input class="form-control" asp-for="Student.Name" />
</div>
<span asp-validation-for="Student.Name" class="text-danger"></span>
</div>
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.StudentClasses.ClassName"></label>
</div>
<div class="col-6">
<select class="form-select" asp-for=" Student.StudentClassId" asp-items="Model.ClassList" >
<option value="">请选择班级</option>
</select>
</div>
<span asp-validation-for="Student.StudentClasses.ClassName" class="text-danger"></span>
</div>
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.Gender"></label>
</div>
<div class="col-6">
<select class="form-select" asp-for="Student.Gender" asp-items="Html.GetEnumSelectList<Gender>()">
<option value="">请选择性别</option>
</select>
</div>
<span asp-validation-for="Student.Gender" class="text-danger"></span>
</div>
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.Age"></label>
</div>
<div class="col-6">
<input class="form-control" asp-for="Student.Age" />
</div>
<span asp-validation-for="Student.Age" class="text-danger"></span>
</div>
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.Phone"></label>
</div>
<div class="col-6">
<input class="form-control" asp-for="Student.Phone" />
</div>
<span asp-validation-for="Student.Phone" class="text-danger"></span>
</div>
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.Address"></label>
</div>
<div class="col-6">
<input class="form-control" asp-for="Student.Address" />
</div>
</div>
<div class="form-group row mb-3">
<div class="col-3">
<label asp-for="Student.Description"></label>
</div>
<div class="col-6">
<input class="form-control" asp-for="Student.Description" />
</div>
</div>
<div class="form-group row mb-3">
<div class="col-3 offset-3">
<input type="submit" value="创建" class="btn btn-primary form-control"/>
</div>
<div class="col-3">
<a asp-page="Index" class="btn btn-success form-control text-white">返回</a>
</div>
</div>
</form>
</div>
@{
// 可以写C#代码
}
后端代码:
cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorStudentManager.AppData;
using RazorStudentManager.Model;
using System.Threading.Tasks;
namespace RazorStudentManager.Pages.StudentPage
{
public class CreateModel : PageModel
{
private readonly AppDbContext _db;
public CreateModel(AppDbContext db)
{
//在构造里注入上下文
_db = db;
}
[BindProperty] //前后端的代码绑定
public Student Student { get; set; }
public SelectList ClassList { get; set; }
public async Task OnGet() //获取数据
{
var items = await _db.StudentClasses.ToListAsync();
ClassList = new SelectList(items,"Id","ClassName");
}
public async Task<IActionResult> OnPost()
{
ModelState.Remove("StudentClasses");
if (ModelState.IsValid) //是 ASP.NET MVC 中用于验证模型状态的属性,表示当前模型是否满足所有验证规则(如Required、StringLength等特性)。若验证通过返回 true,否则返回 false。
{
await _db.AddAsync(Student); //将Student实体类的状态信息添加到数据库上下文
await _db.SaveChangesAsync();//执行到数据库
return RedirectToPage("Index");
}
else
{
return Page();
}
}
}
}