七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接
前言
本章节的主要内容是完善Blazor学生管理页面的编写和接口对接。
七天.NET 8 操作 SQLite 入门到实战详细教程
- 第一天 SQLite 简介
- 第二天 在 Windows 上配置 SQLite 环境
- 第三天 SQLite 快速入门
- 第四天 EasySQLite 前后端项目框架搭建
- 第五天引入 SQLite-net ORM 并封装常用方法
- 第六天后端班级管理相关接口完善和Swagger自定义配置
- 第七天BootstrapBlazor UI组件库引入(1)
- 第七天Blazor班级管理页面编写和接口对接(2)
EasySQLite 项目源码地址
Blazor简介和快速入门
不熟悉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;
}
}
}
DotNetGuide技术社区交流群
- DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
- 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
- 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。
七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接的更多相关文章
- Docker技术入门与实战 第二版-学习笔记-7-数据管理(volume)
Docker 数据管理 为什么要进行数据管理呢?因为当我们在使用container时,可能会在里面创建一些数据或文件,但是当我们停掉或删除这个容器时,这些数据或文件也会同样被删除,这是我们并不想看见的 ...
- C#操作Sqlite快速入门及相关工具收集
Sqlite不需要安装即可使用.Sqlite是不是那个System.Data.SQLite.DLL临时创建了数据库引擎? 1.新建一个WinForm项目,引用System.Data.SQLite.DL ...
- 【图像处理】OpenCV+Python图像处理入门教程(七)图像形态学操作
图像形态学主要从图像内提取分量信息,该分量信息通常对表达图像的特征具有重要意义.例如,在车牌号码识别中,能够使用形态学计算其重要特征信息,在进行识别时,只需对这些特征信息运算即可.图像形态学在目标视觉 ...
- 七、Android学习第六天——SQLite与文件下载(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 七.Android学习第六天——SQLite与文件下载 SQLite SQ ...
- SQLite入门与分析(二)---设计与概念(续)
SQLite入门与分析(二)---设计与概念(续) 写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...
- SQLite 入门教程(三)好多约束 Constraints(转)
转于: SQLite 入门教程(三)好多约束 Constraints 一.约束 Constraints 在上一篇随笔的结尾,我提到了约束, 但是在那里我把它翻译成了限定符,不太准确,这里先更正一下,应 ...
- SQLite 入门教程(四)增删改查,有讲究 (转)
转于: SQLite 入门教程(四)增删改查,有讲究 一.插入数据 INSERT INTO 表(列...) VALUES(值...) 根据前面几篇的内容,我们可以很轻送的创建一个数据表,并向其中插入一 ...
- C#操作SQLite方法实例详解
用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox 用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...
- Java操作Sqlite数据库-jdbc连接
Java操作Sqlite数据库步骤: 1. 导入Sqlite jdbc 本文使用sqlite-jdbc-3.7.2.jar,下载地址 http://pan.baidu.com/s/1kVHAGdD 2 ...
- SQLite入门语句之HAVING和DISTINCT
一.SQLite入门语句之HAVING HAVING 子句允许指定条件来过滤将出现在最终结果中的分组结果. WHERE 子句在所选列上设置条件,而 HAVING 子句则在由 GROUP BY 子句创建 ...
随机推荐
- 一个简单demo展示接口请求超时处理
package main import ( "context" "errors" "fmt" "time" ) type ...
- MySQL学习笔记-数据控制语言
SQL-数据控制语言(DCL) DCL语句用于管理数据库用户,控制数据库的访问权限 一. 管理用户 1. 查询用户 # 访问mysql数据库 use mysql; #查询user表 select * ...
- itest work 开源接口测试&敏捷测试管理平台 9.5.0 GA_u3,优化及修复关键 BUG
(一)itest work 简介 itest work (爱测试) 一站式工作站让测试变得简单.敏捷,"好用.好看,好敏捷" ,是itest wrok 追求的目标.itest w ...
- itest(爱测试)开源接口测试&敏捷测试&极简项目管理 6.6.6 发布,新增接口mock
(一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock 6合1,又有丰富的统计分析.可按测试包 ...
- 使用python在k8s中创建一个pod
要在Kubernetes (k8s) 中使用Python创建一个Pod,你可以使用Kubernetes Python客户端库(通常称为kubernetes或kubernetes-client).以下是 ...
- LeetCode 690. Employee Importance 员工的重要性(C++/Java)
题目: You are given a data structure of employee information, which includes the employee's unique id, ...
- freemarker模板替换生成word
工具类 public static void createWord(Map<String,Object> dataMap, String templateName, String file ...
- window10 java环境变量配置
window10 此电脑 右击属性 相关设置 高级系统配置 点击右下的 环境变量 在系统变量中新增JAVA_HOME=D:\Program Files\Java\jdk1.8.0_25 在系统变量中修 ...
- 为什么https要使用证书
为什么https要使用证书 什么是httpshttps不是一种新的协议,只是http的通信接口部分使用了ssl和tsl协议替代,加入了加密.证书.完整性保护的功能. 加密:共享密钥加密加密和解密公用一 ...
- macOS Big Sur 11.0.1光盘镜像文件制作
https://blog.csdn.net/hymnal/article/details/110393501