.NET Core 学习第三天:Razor Pages 联表查询

实现学生与班级联表查询

准备工作

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

    }
}
相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛3 天前
计算机系统概论——校验码
学习
babe小鑫3 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms3 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下3 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。3 天前
2026.2.25监控学习
学习
im_AMBER3 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J3 天前
从“Hello World“ 开始 C++
c语言·c++·学习