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

    }
}
相关推荐
逆小舟1 小时前
【STM32】第四周学习问题汇总
学习
qq_401780821 小时前
2.信号 完整性(信号上升时间与带宽)
学习
车载测试工程师1 小时前
CAPL学习-ETH功能函数-方法类3
学习·tcp/ip·以太网·capl·canoe
im_AMBER1 小时前
Leetcode 69 正整数和负整数的最大计数
数据结构·笔记·学习·算法·leetcode
richxu202510011 小时前
嵌入式学习之路>单片机核心原理篇>(5)串口通信核心原理
单片机·嵌入式硬件·学习
sponge'1 小时前
opencv学习笔记12:GAN网络
笔记·opencv·学习
会飞的小蛮猪2 小时前
Rockylinux急速安装K8s学习环境
学习·容器·kubernetes
代码游侠2 小时前
数据结构--队列
数据结构·笔记·学习·算法·链表
车载测试工程师2 小时前
CAPL学习-ETH功能函数-方法类2
网络·网络协议·学习·c#·以太网·capl·canoe