前言

本章节我们的主要内容是完善Blazor学生管理页面的编写和接口对接。

七天.NET 8 操作 SQLite 入门到实战详细教程

EasySQLite 项目源码地址

Blazor简介和快速入门

不熟悉Blazor的同学可以先看这篇文章大概了解一下。

全面的ASP.NET Core Blazor简介和快速入门

前端Table页面和接口对接代码

主要是常见Table的数据展示、数据添加、数据删除、数据修改等操作。

@page "/Student"
@using Entity
@using Entity.ViewModel
@using System.Reflection
@using Utility
@using WebUI.Common
@using WebUI.Services
@inject HttpClient _httpClient;
@inject DataLoaderService _dataLoader;

<Table TItem="StudentViewModel"
       AutoGenerateColumns="true"
       ShowToolbar="true"
       IsMultipleSelect="true"
       OnSaveAsync="@OnSaveAsync"
       OnQueryAsync="@OnQueryAsync"
       OnDeleteAsync="@OnDeleteAsync"
       IsStriped="true"
       IsBordered="true"
       ShowSearch="true"
       IsPagination="true"
       ShowSearchText="true">

    <!--通过设置 EditTemplate 自定义编辑弹窗,如果属性需要联动时必须像本例这样封装成一个独立的组件再放置到模板中-->
    <EditTemplate>
        <StudentEditor @bind-Value="context" />
    </EditTemplate>

    <SearchTemplate>
        <GroupBox Title="搜索条件">
            <div class="row g-3 form-inline">
                <div class="col-12 col-sm-6">
                    <BootstrapInput @bind-Value="@context.Name" PlaceHolder="请输入学生姓名" maxlength="50" ShowLabel="true" DisplayText="姓名" />
                </div>
            </div>
        </GroupBox>
    </SearchTemplate>
</Table>

@code {

    /// <summary>
    /// 数据查询
    /// </summary>
    /// <param name="options">options</param>
    /// <returns></returns>
    private async Task<QueryData<StudentViewModel>> OnQueryAsync(QueryPageOptions options)
    {
        var searchModel = options.SearchModel as StudentViewModel;
        var getStudentData = new List<StudentViewModel>();
        var getResults = await _httpClient.GetFromJsonAsync<ApiResponse<List<StudentViewModel>>>("api/Student/GetAllStudent").ConfigureAwait(false);
        if (getResults.Success)
        {
            // 数据模糊过滤筛选
            if (!string.IsNullOrWhiteSpace(options.SearchText))
            {
                getStudentData = getResults.Data.Where(x => x.Name.Contains(options.SearchText)).ToList();
            }
            else if (searchModel != null && !string.IsNullOrWhiteSpace(searchModel.Name))
            {
                getStudentData = getResults.Data.Where(x => x.Name.Contains(searchModel.Name)).ToList();
            }
            else
            {
                getStudentData = getResults.Data.ToList();
            }
        }

        //加载班级信息
        await _dataLoader.LoadSchoolClassDataAsync().ConfigureAwait(false);

        // 内存分页
        return await Task.FromResult(new QueryData<StudentViewModel>()
            {
                Items = getStudentData.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList(),
                TotalCount = getStudentData.Count()
            });
    }

    /// <summary>
    /// 模拟数据增加和修改操作
    /// </summary>
    /// <param name="studentInfo">studentInfo</param>
    /// <param name="changedType">changedType</param>
    /// <returns></returns>
    public async Task<bool> OnSaveAsync(StudentViewModel studentInfo, ItemChangedType changedType)
    {
        if (changedType.ToString() == "Update")
        {
            var addResult = await _httpClient.PutAsJsonAsync($"api/Student/UpdateStudent/{studentInfo.StudentID}", studentInfo).ConfigureAwait(false);
            if (UtilityBusiness.CheckResponse(addResult))
            {
                return await Task.FromResult(true);
            }
            else
            {
                return await Task.FromResult(false);
            }
        }
        else if (changedType.ToString() == "Add")
        {
            var addResult = await _httpClient.PostAsJsonAsync("api/Student/CreateStudent", studentInfo).ConfigureAwait(false);
            if (UtilityBusiness.CheckResponse(addResult))
            {
                return await Task.FromResult(true);
            }
            else
            {
                return await Task.FromResult(false);
            }
        }

        return await Task.FromResult(true);
    }

    /// <summary>
    /// 数据删除
    /// </summary>
    /// <param name="items">items</param>
    /// <returns></returns>
    private async Task<bool> OnDeleteAsync(IEnumerable<StudentViewModel> items)
    {
        var deleteSuccessNum = 0;
        var StudentViewModelList = items.ToList();
        foreach (var item in StudentViewModelList)
        {
            var delResult = await _httpClient.DeleteAsync($"api/Student/DeleteStudent/{item.StudentID}").ConfigureAwait(false);
            if (UtilityBusiness.CheckResponse(delResult))
            {
                deleteSuccessNum++;
            }
        }

        if (deleteSuccessNum > 0)
        {
            return await Task.FromResult(true);
        }
        else
        {
            return await Task.FromResult(false);
        }
    }
}

自定义编辑弹窗模板

StudentEditor.razor:

@using Entity
@using Microsoft.Extensions.Caching.Memory
@using WebUI.Services
@inject HttpClient _httpClient;
@inject DataLoaderService _dataLoader;
@inject IMemoryCache _memoryCache;

<div class="row g-3 form-inline">
    <div class="col-12">
        <BootstrapInput @bind-Value="@Value.ClassID" IsDisabled maxlength="50" />
    </div>
    <div class="col-12">
        <Select @bind-Value="@Value.ClassID" OnSelectedItemChanged="OnSelectedItemChanged" Items="Items" />
    </div>
    <div class="col-12">
        <BootstrapInput @bind-Value="@Value.Name" placeholder="请输入学生名称" maxlength="50" required />
    </div>
    <div class="col-12">
        <Select @bind-Value="@Value.Gender" Items="GenderItems" required />
    </div>
    <div class="col-12">
        <BootstrapInput @bind-Value="@Value.Age" placeholder="请输入年龄" maxlength="50" />
    </div>
</div>

StudentEditor.razor.cs:

using System;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Net.Http.Json;
using System.Xml.Linq;
using BootstrapBlazor.Components;
using Entity;
using Entity.ViewModel;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using WebUI.Services;

namespace WebUI.Pages
{
    public partial class StudentEditor
    {
        [Parameter]
        public StudentViewModel Value { get; set; }

        [Parameter]
        public EventCallback<StudentViewModel> ValueChanged { get; set; }

        [NotNull]
        private List<SelectedItem>? Items { get; set; }

        [NotNull]
        private List<SelectedItem>? GenderItems { get; set; }

        protected override async void OnInitialized()
        {
            base.OnInitialized();
            List<SchoolClass>? getSchoolClass;
            if (_memoryCache.TryGetValue("SchoolClassData", out string data))
            {
                getSchoolClass = JsonConvert.DeserializeObject<List<SchoolClass>>(data);
            }
            else
            {
                getSchoolClass = await _dataLoader.LoadSchoolClassDataAsync().ConfigureAwait(false);
            }

            Items = [];
            foreach (var item in getSchoolClass.OrderBy(x => x.ClassID).ToList())
            {
                Items.Add(new SelectedItem { Value = item.ClassID.ToString(), Text = item.ClassName });
            }

            if (string.IsNullOrWhiteSpace(Value.ClassName))
            {
                Value.ClassName = Items.First().Text;
                Value.ClassID = Convert.ToInt32(Items.First().Value);
            }

            GenderItems = [new SelectedItem { Value = "男", Text = "男" }, new SelectedItem { Value = "女", Text = "女" }];

            if (string.IsNullOrWhiteSpace(Value.Gender))
            {
                Value.Gender = GenderItems.First().Text;
            }
        }

        /// <summary>
        /// 下拉框选项改变时触发此事件
        /// </summary>
        /// <param name="item">item</param>
        /// <returns></returns>
        async Task OnSelectedItemChanged(SelectedItem item)
        {
            await Task.Delay(1);
            Value.ClassID = Convert.ToInt32(item.Value);
        }
    }
}

后端API接口

using AutoMapper;
using Entity;
using Entity.ViewModel;
using Microsoft.AspNetCore.Mvc;
using Utility;

namespace WebApi.Controllers
{
    /// <summary>
    /// 学生管理
    /// </summary>
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class StudentController : ControllerBase
    {
        private readonly IMapper _mapper;
        private readonly SQLiteAsyncHelper<Student> _studentHelper;
        private readonly SQLiteAsyncHelper<SchoolClass> _schoolClassHelper;

        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="mapper">mapper</param>
        /// <param name="studentHelper">studentHelper</param>
        /// <param name="schoolClassHelper">schoolClassHelper</param>
        public StudentController(IMapper mapper, SQLiteAsyncHelper<Student> studentHelper, SQLiteAsyncHelper<SchoolClass> schoolClassHelper)
        {
            _mapper = mapper;
            _studentHelper = studentHelper;
            _schoolClassHelper = schoolClassHelper;
        }

        /// <summary>
        /// 创建新的学生记录
        /// </summary>
        /// <param name="student">添加的学生信息</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResponse<int>> CreateStudent([FromBody] Student student)
        {
            var response = new ApiResponse<int>();
            try
            {
                var insertNumbers = await _studentHelper.InsertAsync(student).ConfigureAwait(false);
                if (insertNumbers > 0)
                {
                    response.Success = true;
                    response.Message = "添加成功";
                }
                else
                {
                    response.Success = false;
                    response.Message = "插入失败";
                }
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.Message = ex.Message;
            }
            return response;
        }

        /// <summary>
        /// 查询所有学生记录
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResponse<List<StudentViewModel>>> GetAllStudent()
        {
            var response = new ApiResponse<List<StudentViewModel>>();
            try
            {
                var students = await _studentHelper.QueryAllAsync().ConfigureAwait(false);
                var studentsListDto = await GetStudentClassInfo(students).ConfigureAwait(false);
                response.Success = true;
                response.Data = studentsListDto ?? new List<StudentViewModel>();
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.Message = ex.Message;
            }
            return response;
        }

        private async Task<List<StudentViewModel>?> GetStudentClassInfo(List<Student> students)
        {
            var studentsListDto = _mapper.Map<List<StudentViewModel>>(students);
            if (studentsListDto?.Count > 0)
            {
                var classIDs = studentsListDto.Select(x => x.ClassID).Distinct().ToList();
                var querySchoolClassList = await _schoolClassHelper.QueryAsync(x => classIDs.Contains(x.ClassID)).ConfigureAwait(false);
                if (querySchoolClassList?.Count > 0)
                {
                    foreach (var studentItem in studentsListDto)
                    {
                        var getClassInfo = querySchoolClassList.FirstOrDefault(x => x.ClassID == studentItem.ClassID);
                        if (getClassInfo != null)
                        {
                            studentItem.ClassName = getClassInfo.ClassName;
                        }
                    }
                }
            }
            return studentsListDto;
        }

        /// <summary>
        /// 根据学生ID查询学生信息
        /// </summary>
        /// <param name="studentID">学生ID</param>
        /// <returns></returns>
        [HttpGet("{studentID}")]
        public async Task<ApiResponse<StudentViewModel>> GetStudentById(int studentID)
        {
            var response = new ApiResponse<StudentViewModel>();
            try
            {
                var student = await _studentHelper
                    .QuerySingleAsync(x => x.StudentID == studentID)
                    .ConfigureAwait(false);
                if (student != null)
                {
                    var studentsDto = await GetStudentClassInfo(new List<Student> { student }).ConfigureAwait(false);
                    response.Success = true;
                    response.Data = studentsDto.FirstOrDefault();
                }
                else
                {
                    response.Success = false;
                    response.Message = "未找到学生信息";
                }
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.Message = ex.Message;
            }
            return response;
        }

        /// <summary>
        /// 更新学生记录
        /// </summary>
        /// <param name="studentID">学生ID</param>
        /// <param name="editstudent">更新的学生信息</param>
        /// <returns></returns>
        [HttpPut("{studentID}")]
        public async Task<ApiResponse<int>> UpdateStudent(
            int studentID,
            [FromBody] Student editstudent
        )
        {
            var response = new ApiResponse<int>();
            try
            {
                var student = await _studentHelper
                    .QuerySingleAsync(x => x.StudentID == studentID)
                    .ConfigureAwait(false);
                if (student != null)
                {
                    student.Age = editstudent.Age;
                    student.Name = editstudent.Name;
                    student.Gender = editstudent.Gender;
                    student.ClassID = editstudent.ClassID;

                    int updateResult = await _studentHelper
                        .UpdateAsync(student)
                        .ConfigureAwait(false);
                    if (updateResult > 0)
                    {
                        response.Success = true;
                        response.Message = "学生信息更新成功";
                    }
                    else
                    {
                        response.Success = false;
                        response.Message = "学生信息更新失败";
                    }
                }
                else
                {
                    response.Success = false;
                    response.Message = "未找到学生信息";
                }
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.Message = ex.Message;
            }
            return response;
        }

        /// <summary>
        /// 删除学生记录
        /// </summary>
        /// <param name="studentID">学生ID</param>
        /// <returns></returns>
        [HttpDelete("{studentID}")]
        public async Task<ApiResponse<int>> DeleteStudent(int studentID)
        {
            var response = new ApiResponse<int>();
            try
            {
                int deleteResult = await _studentHelper
                    .DeleteAsync(studentID)
                    .ConfigureAwait(false);
                if (deleteResult > 0)
                {
                    response.Success = true;
                    response.Message = "删除成功";
                }
                else
                {
                    response.Success = false;
                    response.Message = "未找到学生信息";
                }
            }
            catch (Exception ex)
            {
                response.Success = false;
                response.Message = ex.Message;
            }
            return response;
        }
    }
}

七天.NET 8操作SQLite入门到实战 - 第七天Blazor学生管理页面编写和接口对接(3)的更多相关文章

  1. reactjs入门到实战(七)---- React的组件的生命周期

    React的组件的生命周期有三个状态分别是:挂载(生产组件示例化.准备挂载到页面.挂载到页面).更新(更新值.更新DOM).和卸载(卸载后). >>>其他     getInitia ...

  2. C#操作Sqlite快速入门及相关工具收集

    Sqlite不需要安装即可使用.Sqlite是不是那个System.Data.SQLite.DLL临时创建了数据库引擎? 1.新建一个WinForm项目,引用System.Data.SQLite.DL ...

  3. 【图像处理】OpenCV+Python图像处理入门教程(七)图像形态学操作

    图像形态学主要从图像内提取分量信息,该分量信息通常对表达图像的特征具有重要意义.例如,在车牌号码识别中,能够使用形态学计算其重要特征信息,在进行识别时,只需对这些特征信息运算即可.图像形态学在目标视觉 ...

  4. 七、Android学习第六天——SQLite与文件下载(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 七.Android学习第六天——SQLite与文件下载 SQLite SQ ...

  5. SQLite入门与分析(二)---设计与概念(续)

    SQLite入门与分析(二)---设计与概念(续)   写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...

  6. SQLite 入门教程(三)好多约束 Constraints(转)

    转于: SQLite 入门教程(三)好多约束 Constraints 一.约束 Constraints 在上一篇随笔的结尾,我提到了约束, 但是在那里我把它翻译成了限定符,不太准确,这里先更正一下,应 ...

  7. SQLite 入门教程(四)增删改查,有讲究 (转)

    转于: SQLite 入门教程(四)增删改查,有讲究 一.插入数据 INSERT INTO 表(列...) VALUES(值...) 根据前面几篇的内容,我们可以很轻送的创建一个数据表,并向其中插入一 ...

  8. C#操作SQLite方法实例详解

    用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox  用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...

  9. ArcGIS for Desktop入门教程_第七章_使用ArcGIS进行空间分析 - ArcGIS知乎-新一代ArcGIS问答社区

    原文:ArcGIS for Desktop入门教程_第七章_使用ArcGIS进行空间分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 使用ArcGIS进行空间分析 1.1 GIS分析基础 G ...

  10. Java操作Sqlite数据库-jdbc连接

    Java操作Sqlite数据库步骤: 1. 导入Sqlite jdbc 本文使用sqlite-jdbc-3.7.2.jar,下载地址 http://pan.baidu.com/s/1kVHAGdD 2 ...

随机推荐

  1. js 实现密码框的查看和隐藏

    大江东去,浪淘尽,千古风流人物.故垒西边,人道是,三国周郎赤壁.乱石穿空,惊涛拍岸,卷起千堆雪.江山如画,一时多少豪杰.遥想公瑾当年,小乔初嫁了,雄姿英发.羽扇纶巾,谈笑间,樯橹灰飞烟灭.故国神游,多 ...

  2. JavaSE 流程控制语句if while for

    目录 控制语句 if条件结构 switch语句 switch与if区别 for 循环 while循环 while与do while 控制语句 条件语句 - 根据不同条件,执行不同语句 if if... ...

  3. vue双曲线

    原型 1 <template> 2 <div :class="className" :style="{height:height,width:width ...

  4. Prometheus + Grafana (2) mysql、redis、Docker容器、服务端点以及预警

    接着上一节 <Prometheus + Grafana (1) 监控 >,我们继续探讨 Prometheus + Grafana 的复杂应用 实现目标 这节我们的目标是搭建一个多维度监控微 ...

  5. vue2 混入 (mixin) 带来的小惊喜

    最近在review自己写的代码时发现,在很多的地方都用了以下的代码块 1 async initCode() { 2 const resSource = await this.$API.syscode. ...

  6. Linux chmod -bash: ./xx.sh: Permission denied的解决方案

    Linux -bash: ./xx.sh: Permission denied的解决方案启动tomcat命令:./startup.sh之后提示-bash: ./startup.sh: Permissi ...

  7. 彻底解决C盘不够用的问题(Windows 10)- 常规方法——清垃圾、转虚拟内存、挪大文件

    1.清垃圾 2.转虚拟内存 3.挪大文件

  8. Imdeploy笔记

    Smiling & Weeping ---- 天气不好的时候,我会小心地把自己心上的裂缝补起来.为什么?... LMDeploy 的量化和部署 1 环境配置 2 服务部署 2.1 模型转换 2 ...

  9. 盘点 Spring Boot 解决跨域请求的几种办法

    熟悉 web 系统开发的同学,对下面这样的错误应该不会太陌生. 之所以会出现这个错误,是因为浏览器出于安全的考虑,采用同源策略的控制,防止当前站点恶意攻击 web 服务器盗取数据. 01.什么是跨域请 ...

  10. vue项目中一些常用的插件

    @riophae/vue-treeselect:带选择的树组件 https://vue-treeselect.js.org/ ele-calendar:日历组件 https://www.npmjs.c ...