当前位置: 首页 > news >正文

.NET 7.0 EF Core:一、创建Web API 项目基础框架和用户表的增删改查

demo 地址: https://github.com/iotjin/Jh.Admin.NETCore
代码不定时更新,请前往github查看最新代码

.NET 7.0 EF Core:一、创建Web API项目

  • 官方教程
  • 一、项目目录结构
    • 各层职责说明
      • 1️⃣ Admin.NETCore.API(接口层)
      • 2️⃣ Admin.NETCore.Core(核心业务层)
      • 3️⃣ Admin.NETCore.Infrastructure(基础设施层)
      • 4️⃣ Admin.NETCore.Common(通用功能层)
    • 项目文件结构图
    • 设计的用户表数据结构和返回结构
  • 二、创建Web API项目
  • 三、调整项目结构
  • 四、添加NuGet 包
  • 五、通过CodeFirst建库建表
    • BaseEntity代码
    • User代码
    • UserConfig代码
    • AppDbContext代码
    • 生成数据库和表
  • 六、UserService 实现
    • Services主要代码
    • UserDTO代码
    • UserVModel代码
    • IUserService代码
    • UserService代码
  • 七、UserController 实现
    • UserController代码
  • 八、优化Program.cs
    • Program.cs原来的代码
    • ValidationFiter代码
    • ApplicationBuilderExtensions代码
    • CorsExtensions代码
    • ServiceCollectionExtensions代码
    • SwaggerExtensions代码
    • 修改后的Program.cs代码
    • 运行结果

官方教程

EF Core 官方文档
官方文档: 教程:使用 ASP.NET Core 创建最小 API
EFCore 查询数据
第一个EFCore应用
使用 NuGet 包管理器在 Visual Studio 中安装和管理包
常见的数据库提供程序

NuGet 包网站

本文记录如何使用 MySQL+ .NET 7 + Entity Framework Core (EF Core) + Code First + Fluent API 搭建一个后台管理系统框架。项目采用常见的分层结构,适合后续扩展用户、角色、菜单管理等模块。

  • Admin.NETCore.API:接口入口层(API 层),Web API 入口
  • Admin.NETCore.Core:核心业务层,Interface、Service、ViewModel、DTO等
  • Admin.NETCore.Infrastructure:基础设施层,数据库、Fluent API配置、Entity、Migrations等
  • Admin.NETCore.Common:通用功能层,工具类等

一、项目目录结构

Admin.NETCore
├── Admin.NETCore.API // 接口入口层
├── Admin.NETCore.Core // 核心业务层
├── Admin.NETCore.Infrastructure // 基础设施层
└── Admin.NETCore.Common // 通用功能层

各层职责说明

1️⃣ Admin.NETCore.API(接口层)

负责处理 HTTP 请求和响应,是整个项目的对外入口。

主要目录:

  • Controllers/:控制器,如 UserControllerRoleController
  • Identity/Filters/:请求验证过滤器,如 ValidationFilter.cs
  • ServiceExtensions/:服务注册扩展类(中间件、Swagger、CORS 等)
  • Program.cs:程序主入口
  • appsettings.json:配置文件

2️⃣ Admin.NETCore.Core(核心业务层)

包含系统的业务逻辑、接口定义、DTO/ViewModel,不依赖基础设施层。

主要目录:

  • Interfaces/:接口定义,如 IUserServiceIRoleService
  • Services/:核心业务逻辑的实现
  • ViewModels/:DTO/ViewModel 传输模型,分为 UserDTO, RoleDTO, UserVModel

3️⃣ Admin.NETCore.Infrastructure(基础设施层)

实现所有对数据库的访问逻辑,包含 EF Core 实体、配置和上下文等。

主要目录:

  • Entities/:实体类,如 User, Role, UserRole,继承 BaseEntity
  • Configs/:EF Core 实体映射配置(Fluent API)
  • AppDbContext.cs:EF Core 数据上下文
  • Migrations/:EF Core 数据迁移记录(Code First)

4️⃣ Admin.NETCore.Common(通用功能层)

放置整个项目中通用的类和工具方法。

主要目录:

  • Configs/:全局配置类,如 GlobalConfigs
  • SqlHelper.cs:通用数据库操作帮助类(如直接操作 SQL)

项目文件结构图

依赖关系
在这里插入图片描述

完整层级
在这里插入图片描述

设计的用户表数据结构和返回结构

在这里插入图片描述

二、创建Web API项目

先创建一个带swagger的Web API项目然后再对其进行改造

打开 Visual Studio → 新建项目
选择 ASP.NET Core Web API
项目命名为:Admin.NETCore.API ,解决方案命名为:Admin.NETCore
勾选:
✔ 配置 HTTPS(可选)
✔ 勾选“使用控制器(取消选中以使用最小API)”(我们保留默认控制器)
✔ 启用 OpenAPI 支持(Swagger)

创建完成点击运行,可以看到浏览器的swagger页面

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

三、调整项目结构

右键解决方案,按下面步骤依次创建Admin.NETCore.CommonAdmin.NETCore.CoreAdmin.NETCore.Infrastructure

右键解决方案 → 添加 → 新建项目
选择:类库 (.NET Class Library)
命名为:Admin.NETCore.Common,
选择NET 7.0 (或者创建完成后,右键项目 → 属性 → 将目标框架设置为 .NET 7.0)
创建

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、添加NuGet 包

官方文档:使用 NuGet 包管理器在 Visual Studio 中安装和管理包

使用 EFCore 和MySQL 需要添加以下NuGet包:

  • Microsoft.EntityFrameworkCore.Tools
    EF Core 命令支持,用于数据库生成、迁移、生成表等操作,安装在Admin.NETCore.API

  • Pomelo.EntityFrameworkCore.MySql
    MySQL支持,安装在Admin.NETCore.Infrastructure

如果是其他数据库参考下图 常见的数据库提供程序
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

五、通过CodeFirst建库建表

第一个EFCore应用

1)、先在Admin.NETCore.Infrastructure 下面创建文件夹和文件
2)、然后通过实体类定义用户表(User)的数据结构,使用 Fluent API 在独立的配置类中集中管理表名、主键、字段约束等数据库映射信息
3)、在数据库上下文(AppDbContext)中统一注册实体集合,并自动应用所有配置类
4)、最后使用 EF Core 提供的迁移与数据库更新命令(Add-Migration 和 Update-Database)即可在数据库中生成对应的 User 表结构,实现从代码到数据库的完整同步

在这里插入图片描述

BaseEntity代码

using System.ComponentModel.DataAnnotations.Schema;namespace Admin.NETCore.Infrastructure.DB.Entities
{public abstract class BaseEntity{//public Guid Id { get; set; }  // 使用 Guid 类型,表示 UUID// Guid.NewGuid().ToString().ToLower() 得到id//public string Id { get; set; } = null!;  // 存36位字符串 char    主键要定义基类中public DateTime CreateTime { get; set; }public DateTime UpdateDate { get; set; }public string? CreateBy { get; set; }public string? UpdateBy { get; set; }public bool IsDelete { get; set; } // 是否删除//[Column(TypeName = "DATETIME(6)")] // MySQL 支持高精度时间//public DateTime CreateTime { get; set; } = DateTime.UtcNow;//[Column(TypeName = "DATETIME(6)")]//public DateTime UpdateDate { get; set; } = DateTime.UtcNow;//[Column(TypeName = "VARCHAR(10)")] // 明确指定 VARCHAR 类型//public string CreateBy { get; set; } = "system";//[Column(TypeName = "VARCHAR(10)")]//public string UpdateBy { get; set; } = "system";//[Column(TypeName = "TINYINT(1)")] // MySQL 通常用 TINYINT 表示 bool//public bool IsDelete { get; set; }}
}

User代码

namespace Admin.NETCore.Infrastructure.DB.Entities
{public class User : BaseEntity{//public Guid Id { get; set; }  // 使用 Guid 类型,表示 UUID// Guid.NewGuid().ToString().ToLower() 得到idpublic string Id { get; set; } = null!;  // 存36位字符串 charpublic string Name { get; set; } = null!;  // 姓名public string LoginName { get; set; } = null!;  // 登录用户名public string Phone { get; set; } = null!;  // 手机号public int UserNumber { get; set; }  // 员工编号public string DeptId { get; set; } = null!;  // 部门IDpublic DateTime UserExpiryDate { get; set; }  // 用户有效期止public int Status { get; set; }  // 用户状态(1:启用,0:停用)public int Level { get; set; }  // 级别(1:一级,2:二级 。。。)public double? Money { get; set; }  // 补助,可为空public int? Age { get; set; }  // 年龄,可为空public string? Notes { get; set; }  // 备注,最多100个字符}
}

UserConfig代码

using Admin.NETCore.Infrastructure.DB.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;namespace Admin.NETCore.Infrastructure.DB.configs
{public class UserConfig : IEntityTypeConfiguration<User>{public void Configure(EntityTypeBuilder<User> builder){// 设置表名builder.ToTable("User");builder.HasKey(e => e.Id); // 设置主键// 属性配置builder.Property(e => e.Id).HasMaxLength(36);builder.Property(e => e.Name).HasMaxLength(10).IsRequired().HasComment("姓名");builder.Property(e => e.LoginName).HasMaxLength(10).HasColumnType("varchar(10)").IsRequired();builder.Property(e => e.Phone).HasMaxLength(11).IsRequired().IsFixedLength().HasAnnotation("PhoneNumber", "^[0-9]{11}$"); // 正则校验(可以自定义更复杂的格式)builder.Property(e => e.UserNumber).HasMaxLength(8).IsRequired();  // 数值类型(如 int)无法添加长度限制,此处HasMaxLength不生效builder.Property(e => e.DeptId).IsRequired(); // 不设置长度,类型为longtextbuilder.Property(e => e.UserExpiryDate).HasMaxLength(10).IsRequired(); // DateTime类型,无法添加长度限制,此处HasMaxLength不生效builder.Property(e => e.Status).IsRequired();builder.Property(e => e.Level).IsRequired();builder.Property(e => e.Money).IsRequired(false);builder.Property(e => e.Age).IsRequired(false).HasAnnotation("Age", "^[1-9][0-9]*$");builder.Property(e => e.Notes).HasMaxLength(100).IsRequired(false).HasComment("这是备注");// 公共属性配置builder.Property(e => e.CreateBy).IsRequired(false).HasMaxLength(10).HasColumnName("CreateBy");builder.Property(e => e.UpdateBy).IsRequired(false).HasMaxLength(10).HasColumnName("UpdateBy");// 创建时间(只设置一次)builder.Property(e => e.CreateTime).HasColumnName("CreateTime").HasColumnType("DATETIME(6)").ValueGeneratedOnAdd().HasDefaultValueSql("CURRENT_TIMESTAMP(6)") // GETDATE() SQL Server  / NOW() mysql  GETUTCDATE().Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);// 更新时间(每次更新)builder.Property(e => e.UpdateDate).HasColumnName("UpdateDate").HasColumnType("DATETIME(6)").ValueGeneratedOnAddOrUpdate().HasDefaultValueSql("CURRENT_TIMESTAMP(6)") // .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);//builder.Ignore(e => e.CreateTime);// 设置某字段不映射到数据表//builder.Property(e => e.IsDelete).HasColumnName("delFlag"); // 某字段对应数据表的某字段}}
}/*EF默认规则是“主键属性不允许为空,引用类型允许为空,可空的值类型long?等允许为空,值类型不允许为空。”
基于“尽量少配置”的原则:如果属性是值类型并且允许为null,就声明成long?等,否则声明成long等;
如果属性属性值是引用类型,只有不允许为空的时候设置IsRequired()。其他一般不用设置的
主键:this.HasKey(p => p.pId);
某个字段不参与映射数据库:this.Ignore(p => p.Name1);
this.Property(p => p.Name).IsFixedLength(); 是否对应固定长度
this.Property(p => p.Name).IsUnicode(false) 对应的数据库类型是varchar类型,而不是nvarchar
this.Property(p => p.Id).HasColumnName(“Id”); Id列对应数据库中名字为Id的字段
this.Property(p=>p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity) 指定字段是自动增长类型。*/

AppDbContext代码

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Reflection;
using Admin.NETCore.Infrastructure.DB.Entities;namespace Admin.NETCore.Infrastructure.DB
{/// <summary>/// 应用数据库上下文,用于管理 EF Core 与数据库之间的交互/// </summary>public class AppDbContext : DbContext{public AppDbContext(DbContextOptions<AppDbContext> options) : base(options){}/*用户表(User 实体)对应的数据集合,AppDbContext 可以对 User 实体进行增删查改操作DbSet<T> 是 EF Core 中用于操作某个实体类型的集合放在 AppDbContext 中,EF Core 会自动识别这些属性,对应到数据库的表,进行 Code First 映射*/public DbSet<User> User { get; set; } //  DbSet<模型> 表名public DbSet<Role> Role { get; set; }public DbSet<UserRole> UserRole { get; set; }/** 数据库配置建议在 Program.cs 中完成(使用依赖注入方式)* 如果在这里同时使用 OnConfiguring,会导致配置冲突或冗余。* 所以此处注释掉 OnConfiguring 方法*///protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)//{//    // 数据库连接字符串//    var connectionString = "server=localhost;Database=TestDB;Uid=root;Pwd=root;";//    // 使用 MySQL 数据库,并指定服务器版本//    optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));//     base.OnConfiguring(optionsBuilder);//}/// <summary>/// 模型构建方法,用于配置实体与数据库的映射关系/// </summary>protected override void OnModelCreating(ModelBuilder modelBuilder){// ❎ 下面是手动配置实体属性的示例,仅供参考,实际建议写在单独的配置类中//modelBuilder.Entity<User>().Property(e => e.Name)//    .IsRequired()//    .HasComment("备注");//modelBuilder.Entity<User>(entity =>//{//    entity.ToTable("User");//    // 属性配置//    entity.HasKey(e => e.Id); // 设置主键//    entity.Property(e => e.Id).HasMaxLength(36);//    entity.Property(e => e.Name).HasMaxLength(10).IsRequired().HasComment("姓名");//    entity.Property(e => e.LoginName).HasMaxLength(10).IsRequired();//    entity.Property(e => e.Phone).HasMaxLength(11).IsRequired().IsFixedLength().HasAnnotation("PhoneNumber", "^[0-9]{11}$"); // 正则校验(可以自定义更复杂的格式)//    entity.Property(e => e.UserNumber).HasMaxLength(8).IsRequired();//    entity.Property(e => e.DeptId).IsRequired();//    entity.Property(e => e.UserExpiryDate).HasMaxLength(10).IsRequired();//    entity.Property(e => e.Status).IsRequired();//    entity.Property(e => e.Level).IsRequired();//    entity.Property(e => e.Money).IsRequired(false);//    entity.Property(e => e.Age).IsRequired(false).HasAnnotation("Age", "^[1-9][0-9]*$");//    entity.Property(e => e.Notes).HasMaxLength(100).IsRequired(false).HasComment("这是备注");//});base.OnModelCreating(modelBuilder);//方式一. 分开注册, 逐个添加实体的配置类//modelBuilder.Configurations.Add(new UserConfig());//modelBuilder.Configurations.Add(new RoleConfig());//方式二. 一次性加载所有Fluent API的配置// ✅ 推荐方式:统一加载所有 IEntityTypeConfiguration 的配置类(如 UserConfig、RoleConfig 等)modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());}}}/* Migration的一些命令(因为在Program中配置了 MigrationsAssembly对应的项目,这里放在配置的项目路径下) 工具>NuGet 包管理器 > 程序包管理器控制台Add-Migration Init update-database 指定 Migration 路径Add-Migration updateUserTable6 -OutputDir "DB/Migrations"*/

生成数据库和表

1)、在 Program.cs中注册 AppDbContext,并指定 EF Core 使用 MySQL 作为数据库

builder.Services.AddDbContext<AppDbContext>(options =>options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"),ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection")),x => x.MigrationsAssembly("Admin.NETCore.Infrastructure") // 指定迁移程序集
));var app = builder.Build();

2)、在 appsettings中添加连接字符串

  "ConnectionStrings": {"DefaultConnection": "server=localhost;Database=TestDB;Uid=root;Pwd=root;"}

3)、生成Migration

// Install-Package Microsoft.EntityFrameworkCore.Tools
Add-Migration InitialCreate
Update-Database

通过Add-Migration xxx 命令生成Migration 迁移文件
作用:用于创建数据库迁移文件。根据当前的实体模型和配置类,生成一份数据库结构的变更快照(Migration 迁移文件)

在这里插入图片描述
在这里插入图片描述
4)、应用到数据库

通过Update-Database 命令将迁移应用到数据库中,创建相应的数据表结构

在这里插入图片描述
在这里插入图片描述

六、UserService 实现

1)、先在Admin.NETCore.CoreAdmin.NETCore.Common下面创建文件夹和文件
2)、在Service实现代码

在这里插入图片描述

Services主要代码

最新代码UserService.cs

UserDTO代码

using Admin.NETCore.Core.ViewModels.Base;namespace Admin.NETCore.Core.ViewModels
{public class UserDTO : BaseModel{public string Id { get; set; } = null!;public string Name { get; set; } = null!;public string LoginName { get; set; } = null!;public string Phone { get; set; } = null!;public int UserNumber { get; set; }public string DeptId { get; set; } = null!;public DateTime UserExpiryDate { get; set; }public int Status { get; set; }public int Level { get; set; }public double? Money { get; set; }public int? Age { get; set; }public string? Notes { get; set; }}
}

UserVModel代码

using Admin.NETCore.Core.ViewModels.Base;
using System.ComponentModel.DataAnnotations;namespace Admin.NETCore.Core.ViewModels
{public class UserVModel : BaseModel{public string? Id { get; set; }[Required(ErrorMessage = "Name不能为空")]public string Name { get; set; } = null!;[Required(ErrorMessage = "LoginName不能为空")]public string LoginName { get; set; } = null!;//[MaxLength(11, ErrorMessage = "Phone必须为11位")]//[MinLength(11, ErrorMessage = "Phone必须为11位")]//[StringLength(11, MinimumLength = 11, ErrorMessage = "Phone长度必须为11位[Required(ErrorMessage = "Phone不能为空")][RegularExpression(@"^1[3-9]\d{9}$", ErrorMessage = "手机号格式不正确")]public string Phone { get; set; } = null!;[Required(ErrorMessage = "UserNumber不能为空")][RegularExpression(@"^\d{8}$", ErrorMessage = "UserNumber必须为8位纯数字")]public int UserNumber { get; set; }[Required(ErrorMessage = "DeptId不能为空")]public string DeptId { get; set; } = null!;public DateTime UserExpiryDate { get; set; }public int Status { get; set; }[Range(1, 10, ErrorMessage = "Level需在0-10范围内")]public int Level { get; set; }public double? Money { get; set; }[Range(1, int.MaxValue, ErrorMessage = "Age必须是正整数")]public int? Age { get; set; }public string? Notes { get; set; }}public class UserFilterModel{public string? Name { get; set; }public string? UserNumber { get; set; }public string? DeptId { get; set; }public string? StartDate { get; set; }public string? EndDate { get; set; }public int Page { get; set; }public int Limit { get; set; }}public class AssignRoleVModel{[Required(ErrorMessage = "UserId不能为空")]public string Id { get; set; } = null!;public List<string> RoleIds { get; set; } = new();}
}

IUserService代码


using Admin.NETCore.Core.ViewModels;
using Admin.NETCore.Core.ViewModels.Base;namespace Admin.NETCore.Core.Interfaces
{public interface IUserService{Task<ApiResult<UserVModel>> CreateUserAsync(UserVModel user);Task<ApiResult<UserVModel>> UpdateUserAsync(UserVModel model);Task<ApiResult<UserVModel>> GetUserByIdAsync(string id);Task<ApiResult<string>> DeleteUserByIdAsync(string id);Task<PagedResult<UserDTO>> GetUserListAsync(UserFilterModel filter);}
}

UserService代码

using Microsoft.EntityFrameworkCore;
using Admin.NETCore.Common.Configs;
using Admin.NETCore.Core.Interfaces;
using Admin.NETCore.Core.ViewModels;
using Admin.NETCore.Core.ViewModels.Base;
using Admin.NETCore.Infrastructure.DB;
using Admin.NETCore.Infrastructure.DB.Entities;namespace Admin.NETCore.Core.Services
{public class UserService : IUserService{private readonly AppDbContext _context;public UserService(AppDbContext context){_context = context;}public async Task<ApiResult<UserVModel>> CreateUserAsync(UserVModel model){//var result = new ApiResult<UserVModel>();// 检查用户名是否已存在if (await _context.User.AnyAsync(m => m.LoginName == model.LoginName)){return ApiResult<UserVModel>.FailResult("登录名已存在");}var dbModel = new User{Id = Guid.NewGuid().ToString(),Name = model.Name,LoginName = model.LoginName,Phone = model.Phone,UserNumber = model.UserNumber,DeptId = model.DeptId,UserExpiryDate = model.UserExpiryDate,Status = model.Status,Level = model.Level,Money = model.Money,Age = model.Age,Notes = model.Notes,IsDelete = false};await _context.User.AddAsync(dbModel);await _context.SaveChangesAsync();var returnModel = model;returnModel.Id = dbModel.Id;return ApiResult<UserVModel>.SuccessResult(returnModel, "用户创建成功");}public async Task<ApiResult<UserVModel>> UpdateUserAsync(UserVModel model){var user = await _context.User.FindAsync(model.Id);if (user == null){return ApiResult<UserVModel>.FailResult("用户不存在");}//    检查用户名是否与其他用户重复if (await _context.User.AnyAsync(m => m.LoginName == model.LoginName && m.Id != model.Id)){return ApiResult<UserVModel>.FailResult("登录名已存在");}user.Name = model.Name;user.LoginName = model.LoginName;user.Phone = model.Phone;user.UserNumber = model.UserNumber;user.DeptId = model.DeptId;user.UserExpiryDate = model.UserExpiryDate;user.Status = model.Status;user.Level = model.Level;user.Money = model.Money;user.Age = model.Age;user.Notes = model.Notes;user.IsDelete = false;await _context.SaveChangesAsync();var returnModel = model;returnModel.Id = user.Id;return ApiResult<UserVModel>.SuccessResult(returnModel, "用户更新成功");}public async Task<ApiResult<string>> DeleteUserByIdAsync(string id){var user = await _context.User.FindAsync(id);if (user == null){return ApiResult<string>.FailResult("用户不存在");}_context.User.Remove(user); // 物理删除//user.IsDelete = true; // 逻辑删除await _context.SaveChangesAsync();return ApiResult<string>.SuccessResult("", "用户删除成功");}public async Task<ApiResult<UserVModel>> GetUserByIdAsync(string id){var user = await _context.User.FindAsync(id);if (user == null){return ApiResult<UserVModel>.FailResult("用户不存在");}var returnModel = new UserVModel{Id = user.Id,Name = user.Name,LoginName = user.LoginName,Phone = user.Phone,UserNumber = user.UserNumber,DeptId = user.DeptId,UserExpiryDate = user.UserExpiryDate,Status = user.Status,Level = user.Level,Money = user.Money,Age = user.Age,Notes = user.Notes,IsDelete = user.IsDelete};return ApiResult<UserVModel>.SuccessResult(returnModel);}public async Task<PagedResult<UserDTO>> GetUserListAsync(UserFilterModel filter){// 参数校验filter.Page = filter.Page > 0 ? filter.Page : 1;filter.Limit = filter.Limit > 0 ? filter.Limit : GlobalConfigs.DefaultPageSize;var query = _context.User.AsNoTracking().AsQueryable();/*EF Core 默认会追踪查询出来的实体(用于之后的更新或删除)如果只是读取数据,无需修改,可以用 .AsNoTracking() 提高性能它会 减少内存开销 和 避免不必要的跟踪逻辑*///var query = _context.User.Where(m => m.IsDelete == false).AsNoTracking().AsQueryable();//var query = _context.User.Where(m => !m.IsDelete).AsNoTracking();// 姓名模糊查询if (!string.IsNullOrEmpty(filter.Name))query = query.Where(m => EF.Functions.Like(m.Name, $"%{filter.Name}%"));// 员工编号模糊查询if (!string.IsNullOrEmpty(filter.UserNumber))query = query.Where(m => m.UserNumber.ToString().Contains(filter.UserNumber));// 部门ID模糊查询if (!string.IsNullOrEmpty(filter.DeptId))query = query.Where(m => m.DeptId == filter.DeptId);// 处理日期范围if (DateTime.TryParse(filter.StartDate, out DateTime startDate))query = query.Where(m => m.CreateTime >= startDate);if (DateTime.TryParse(filter.EndDate, out DateTime endDate))query = query.Where(m => m.CreateTime <= endDate);// 获取总数int total = await query.CountAsync();// 分页查询var users = await query.OrderByDescending(m => m.UpdateDate).Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit).AsSplitQuery().Select(m => new UserDTO{Id = m.Id,Name = m.Name,LoginName = m.LoginName,Phone = m.Phone,UserNumber = m.UserNumber,DeptId = m.DeptId,UserExpiryDate = m.UserExpiryDate,Status = m.Status,Level = m.Level,Money = m.Money,Age = m.Age,Notes = m.Notes,IsDelete = m.IsDelete}).ToListAsync();return PagedResult<UserDTO>.SuccessResult(users, total);}}
}

七、UserController 实现

1)、先在Admin.NETCore.API 下面创建UserController文件
2)、在UserController实现代码
3)、在Program.cs 注册依赖注入

builder.Services.AddScoped<IUserService, UserService>();var app = builder.Build();

UserController代码

using Microsoft.AspNetCore.Mvc;
using Admin.NETCore.Core.Interfaces;
using Admin.NETCore.Core.ViewModels;
using Admin.NETCore.Core.ViewModels.Base;namespace Admin.NETCore.API.Controllers
{[ApiController][Route("api/[controller]/[action]")] // RPC风格, api/[控制器名称]/函数名称//[Route("api/[controller]")]  // RESTful 风格public class UserController : ControllerBase{private readonly IUserService _userService;public UserController(IUserService userService){_userService = userService;}[HttpPost]public async Task<ApiResult<UserVModel>> CreateUserAsync(UserVModel model){if (string.IsNullOrEmpty(model.LoginName)){return ApiResult<UserVModel>.FailResult("用户名不能为空");}return await _userService.CreateUserAsync(model);}[HttpPost]public async Task<ApiResult<UserVModel>> UpdateUserAsync(UserVModel model){if (string.IsNullOrEmpty(model.LoginName)){return ApiResult<UserVModel>.FailResult("用户名不能为空");}return await _userService.UpdateUserAsync(model);}//[HttpGet("{id}")] // 接口格式为 /api/user/GetUserById/123[HttpGet] // 接口格式为 /api/user/GetUserById?id=123public async Task<ApiResult<UserVModel>> GetUserByIdAsync(string id){if (string.IsNullOrEmpty(id)){return ApiResult<UserVModel>.FailResult("id不能为空");}return await _userService.GetUserByIdAsync(id);}[HttpPost]public async Task<ApiResult<string>> DeleteUserByIdAsync([FromBody] IDRequest request){if (string.IsNullOrEmpty(request.Id)){return ApiResult<string>.FailResult("id不能为空");}return await _userService.DeleteUserByIdAsync(request.Id);}[HttpGet]public async Task<PagedResult<UserDTO>> GetUserListAsync([FromQuery] UserFilterModel filter){return await _userService.GetUserListAsync(filter);}}
}

运行项目后,在swagger点创建用户接口 /api/User/CreateUser/api/User/GetUserList 如下

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

点创建用户接口 /api/User/CreateUser, 什么都不改,可以看到返回的数据并不是预期的结构,这是因为使用的是默认的校验,没有用自定义校验,在下一步优化

 {"code": 200,"msg": "success","data": {}}

在这里插入图片描述

八、优化Program.cs

现在Program.cs 完整代码如下,东西都写在一个文件了,以后如果加上像swagger配置、依赖注入、参数校验、中间件等,文件会越来越多,把代码都抽出来,保持主入口简洁

Program.cs原来的代码

using Admin.NETCore.Core.Interfaces;
using Admin.NETCore.Core.Services;
using Admin.NETCore.Infrastructure.DB;
using Microsoft.EntityFrameworkCore;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();builder.Services.AddDbContext<AppDbContext>(options =>options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"),ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection")),x => x.MigrationsAssembly("Admin.NETCore.Infrastructure") // 指定迁移程序集
));builder.Services.AddScoped<IUserService, UserService>();var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();app.Run();

先把文件都创建好,然后在调整

在这里插入图片描述

ValidationFiter代码

// 自定义异常处理类
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Http;namespace Admin.NETCore.API.Identity.filters
{public class ValidationFilterAttribute : ActionFilterAttribute{public override void OnActionExecuting(ActionExecutingContext context){if (!context.ModelState.IsValid){// 提取所有错误信息var errorMessages = context.ModelState.Values.Where(x => x.Errors.Count > 0).SelectMany(x => x.Errors).Select(x => x.ErrorMessage).ToList();// 拼接错误信息为字符串var msgs = string.Join("; ", errorMessages);int statusCode = 201;// 构造自定义响应对象var response = new{code = statusCode,msg = msgs,success = false,data = ""};context.Result = new BadRequestObjectResult(response);// 自定义状态码//context.Result = new ObjectResult(response)//{//    StatusCode = statusCode //};}}}public class CustomValidationFilter : IAsyncActionFilter{public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){if (!context.ModelState.IsValid){//var errorMessages = context.ModelState.Values//                    .Where(x => x.Errors.Count > 0)//                   .SelectMany(x => x.Errors)//                   .Select(x => x.ErrorMessage)//                   .ToList();//var msgs = string.Join("; ", errorMessages);//var response = new//{//    code = 201, // 可根据需求调整//    msg = msgs,//    success = false,//    data = ""//};//context.Result = new BadRequestObjectResult(response);context.Result = CreateValidationErrorResult(context.ModelState);return;}await next();}private static IActionResult CreateValidationErrorResult(ModelStateDictionary modelState){var errorMessages = modelState.Where(x => x.Value?.Errors.Count > 0).ToDictionary(x => x.Key,x => x.Value?.Errors.Select(error =>!string.IsNullOrEmpty(error.ErrorMessage)? error.ErrorMessage: error.Exception?.Message ?? "Unknown error").ToArray());var message = string.Join("; ", errorMessages.SelectMany(e => e.Value ?? Array.Empty<string>()));int statusCode = 201;var response = new{code = statusCode, // 可根据需求调整msg = message,errors = errorMessages,success = false,data = ""};return new BadRequestObjectResult(response); 自定义状态码//return new ObjectResult(response)//{//    StatusCode = statusCode//};}}
}

ApplicationBuilderExtensions代码

using Admin.NETCore.Infrastructure.DB;
using Microsoft.EntityFrameworkCore;namespace Admin.NETCore.API.ServiceExtensions
{public static class ApplicationBuilderExtensions{public static WebApplication ConfigureMiddlewarePipeline(this WebApplication app){// 异常处理应放在最前面app.UseExceptionHandler("/error");// Swaggerapp.UseCustomSwaggerUI();//app.UseCustomSwaggerUI22();if (app.Environment.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseHsts();app.UseHttpsRedirection();}app.UseRouting();// 健康检查端点app.MapHealthChecks("/health");// 全局日志中间件app.UseRequestLogging();app.UseCorsPolicy();app.UseAuthentication();app.UseAuthorization();app.MapControllers();// 可选:数据库自动迁移//app.ApplyMigrations<AppDbContext>();return app;}private static IApplicationBuilder UseRequestLogging(this IApplicationBuilder builder){return builder.Use(async (context, next) =>{var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();logger.LogInformation("Request {Method} {Path}", context.Request.Method, context.Request.Path);await next();logger.LogInformation("Response {StatusCode}", context.Response.StatusCode);});}public static void ApplyMigrations<TContext>(this WebApplication app) where TContext : DbContext{using var scope = app.Services.CreateScope();var db = scope.ServiceProvider.GetRequiredService<TContext>();db.Database.Migrate();}}
}

CorsExtensions代码

namespace Admin.NETCore.API.ServiceExtensions
{public static class CorsExtensions{public static IServiceCollection AddCorsPolicy(this IServiceCollection services){// 配置跨域services.AddCors(c => c.AddPolicy("any", p => p.AllowAnyHeader().AllowAnyOrigin().AllowAnyMethod()));return services;}public static IApplicationBuilder UseCorsPolicy(this IApplicationBuilder app){app.UseCors("any");return app;}}
}

ServiceCollectionExtensions代码

using Admin.NETCore.API.Identity.filters;
using Admin.NETCore.Core.Interfaces;
using Admin.NETCore.Core.Services;
using Admin.NETCore.Infrastructure.DB;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;namespace Admin.NETCore.API.ServiceExtensions
{public static class ServiceCollectionExtensions{private const string MigrationAssembly = "Admin.NETCore.Infrastructure";public static IServiceCollection AddBasicServices(this IServiceCollection services, IConfiguration configuration){// Add services to the container.services.AddControllers();services.AddHealthChecks();// 日志配置services.AddLogging(logging =>{logging.AddConfiguration(configuration.GetSection("Logging"));logging.AddConsole();logging.AddDebug();});services.AddCorsPolicy();services.AddSwaggerConfig();// services.AddSwaggerConfig22();return services;}public static IServiceCollection AddDataBaseServices(this IServiceCollection services, IConfiguration configuration){var connectionString = configuration.GetConnectionString("DefaultConnection")?? throw new InvalidOperationException("缺少数据库连接字符串配置");// services.AddDbContext<AppDbContext>(options =>services.AddDbContextPool<AppDbContext>(options =>options.UseMySql(connectionString,ServerVersion.AutoDetect(connectionString),x => x.MigrationsAssembly(MigrationAssembly) // 指定迁移程序集));services.AddScoped<IUserService, UserService>();return services;}public static IServiceCollection AddControllerWithValidation(this IServiceCollection services){services.AddControllers(options =>{options.Filters.Add<ValidationFilterAttribute>();options.Filters.Add<CustomValidationFilter>();});// 禁用默认的模型验证响应services.Configure<ApiBehaviorOptions>(options =>{options.SuppressModelStateInvalidFilter = true;});return services;}}
}/* 数据库配置// 添加数据库上下文
//builder.Services.AddDbContext<AppDbContext>(options =>
//    options.UseMySql(
//        builder.Configuration.GetConnectionString("DefaultConnection"),
//        ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection"))
//    ));//builder.Services.AddDbContext<AppDbContext>(options =>
//    options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"),
//        new MySqlServerVersion(new Version(8, 0, 21))));//builder.Services.AddDbContext<AppDbContext>(options =>
//    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));//  指定迁移程序集//builder.Services.AddDbContext<AppDbContext>(options =>
//    options.UseMySql(
//        builder.Configuration.GetConnectionString("DefaultConnection"),
//        ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection")),
//        x => x.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name)
//    ));*/

SwaggerExtensions代码

using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;// 通过[ApiExplorerSettings(GroupName = "v1")] 实现
namespace Admin.NETCore.API.ServiceExtensions
{public static class SwaggerExtensions{public static IServiceCollection AddSwaggerConfig(this IServiceCollection services){// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckleservices.AddEndpointsApiExplorer();//services.AddSwaggerGen();services.AddSwaggerGen(options =>{options.SwaggerDoc("v1", new OpenApiInfo{Title = "API (V1)",Version = "v1",//Description = "API 文档1",Description = "🚨 此版本已废弃,请使用 v2",});options.SwaggerDoc("v2", new OpenApiInfo{Title = "API (V2)",Version = "v2",Description = "API 文档2"});// 核心逻辑:根据 GroupName 过滤接口到对应文档options.DocInclusionPredicate((docName, apiDesc) =>{// 获取 Controller/Action 上的 GroupNamevar groupName = apiDesc.ActionDescriptor.EndpointMetadata.OfType<ApiExplorerSettingsAttribute>().FirstOrDefault()?.GroupName;// 未标记 GroupName 的接口默认显示在所有文档中if (string.IsNullOrEmpty(groupName)) return true;// 匹配当前 Swagger 文档名,只有标记了 GroupName 的接口才显示(如 v1/v2)return groupName == docName;});options.OperationFilter<InheritedObsoleteOperationFilter>(); // 注册自定义过滤器 解决 Schema ID 冲突问题//options.CustomSchemaIds(type => type.FullName); // 使用完整命名空间});return services;}public static WebApplication UseCustomSwaggerUI(this WebApplication app){// 获取 IConfigurationvar configuration = app.Services.GetRequiredService<IConfiguration>();// 获取配置EnableSwaggerbool enableSwagger = configuration.GetValue<bool>("EnableSwagger", false);if (app.Environment.IsDevelopment() && enableSwagger){app.UseSwagger();//app.UseSwaggerUI();app.UseSwaggerUI(c =>{c.SwaggerEndpoint("/swagger/v2/swagger.json", "versionV2"); // 这个顺序影响swagger select a definition 默认选中c.SwaggerEndpoint("/swagger/v1/swagger.json", "versionV1 (Deprecated)");// API 文档的默认展开方式c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.List); // 展开分组//c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None); // 默认折叠//c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.Full); // 完全展开所有 API 的详细描述(包括请求参数、响应模型等)//c.DefaultModelsExpandDepth(-1); // -1:完全折叠,不显示任何模型详情。0:展开模型的顶层属性(单层展开)。1或更高:展开到指定层级。});}// 动态处理根路径重定向app.MapGet("/", context =>{if (enableSwagger){// 重定向到 Swagger 页面context.Response.Redirect("/swagger");return Task.CompletedTask;}else{// 返回其他信息(例如 API 状态)context.Response.ContentType = "text/plain; charset=utf-8";return context.Response.WriteAsync($"API 运行中({(app.Environment.IsDevelopment() ? "Development" : "Production")}),Swagger 已禁用。");}});//app.Use(async (context, next) =>//{//    if (context.Request.Path == "/")//    {//        // 返回自定义响应//        context.Response.ContentType = "text/plain; charset=utf-8";//        await context.Response.WriteAsync("API 运行中,Swagger 已禁用");//        return;//    }//    await next();//});return app;}}// 若希望所有继承自 V1BaseController 的子类自动标记为废弃,可通过自定义过滤器实现。public class InheritedObsoleteOperationFilter : IOperationFilter{public void Apply(OpenApiOperation operation, OperationFilterContext context){// 检查控制器是否继承自带有 [Obsolete] 的基类var controllerType = context.MethodInfo.DeclaringType;var baseType = controllerType?.BaseType;if (baseType != null && baseType.GetCustomAttributes(typeof(ObsoleteAttribute), true).Any()){operation.Deprecated = true; // 标记操作已废弃operation.Description += " (已废弃:此接口所属控制器基类已废弃)";}}}
}

最后把Program.cs 调整一下,把Swagger配置项加到appsettings

  "EnableSwagger": true,

修改后的Program.cs代码


using Admin.NETCore.API.ServiceExtensions;var builder = WebApplication.CreateBuilder(args);// Services 配置
builder.Services.AddBasicServices(builder.Configuration);
builder.Services.AddDataBaseServices(builder.Configuration);
builder.Services.AddControllerWithValidation();//if (builder.Environment.IsDevelopment() && builder.Configuration.GetValue<bool>("EnableSwagger", false))
//{
//    builder.Services.AddSwaggerConfig();
//}var app = builder.Build();app.ConfigureMiddlewarePipeline();// Swagger
//if (builder.Environment.IsDevelopment() && builder.Configuration.GetValue<bool>("EnableSwagger", false))
//{
//    app.UseCustomSwaggerUI();
//}app.Run();

运行结果

运行后,页面如下

在这里插入图片描述

运行后,页面如下

在这里插入图片描述

至此结束

相关文章:

.NET 7.0 EF Core:一、创建Web API 项目基础框架和用户表的增删改查

demo 地址: https://github.com/iotjin/Jh.Admin.NETCore 代码不定时更新&#xff0c;请前往github查看最新代码 .NET 7.0 EF Core&#xff1a;一、创建Web API项目 官方教程序一、项目目录结构各层职责说明1️⃣ Admin.NETCore.API&#xff08;接口层&#xff09;2️⃣ Admin.…...

一篇文章了解XML

一、什么是 XML&#xff1f; XML 是一种结构化数据的标记语言&#xff0c;用来存储、传输和描述数据。 它和 HTML 很像&#xff0c;但它的标签是自定义的&#xff0c;不限定格式和外观&#xff0c;而是强调数据的结构和含义。 XML不是用来展示数据的&#xff0c;HTML是用来展…...

Windows下安装zookeeper

有关Linux安装zk的文章可以参考下我之前写的&#xff1a; Zookeeper 3.8.4 安装和参数解析 Windows下的下载和Linux是一样的&#xff0c;都是同一个包&#xff0c;目前zk稳定版是 3.8.4 下载解压后 在根目录下创建 data 文件夹用来存放数据文件 在 conf 文件夹中&#xff0c;…...

计算机网络 网络层:控制平面

在本章中&#xff0c;包含网络层的控制平面组件。控制平面作为一种网络范围的逻辑&#xff0c;不仅控制沿着从源主机到目的主机的端到端路径间的路由器如何转发数据报&#xff0c;而且控制网络层组件和服务如何配置和管理。5.2节&#xff0c;传统的计算图中最低开销路径的路由选…...

探索阿里云智能媒体管理IMM:解锁媒体处理新境界

一、引言&#xff1a;开启智能媒体管理新时代 在数字化浪潮的席卷下&#xff0c;媒体行业正经历着前所未有的变革。从传统媒体到新媒体的转型&#xff0c;从内容生产到传播分发&#xff0c;每一个环节都在寻求更高效、更智能的解决方案。而云计算&#xff0c;作为推动这一变革…...

微信点餐小程序—美食物

本项目是基于WAMP Server 和PHP 动态网页技术构建的微信小程序点餐系统&#xff0c;该系统主要分为前端&#xff08;微信小程序&#xff09;和后端&#xff08;基于PHPMySQL服务器端&#xff09; 整体架构流程 1、前端部分 用户界面&#xff1a;展示菜品、处理用户点餐操作、…...

Python零基础入门到高手8.5节: 实现选择排序算法

目录 8.5.1 排序算法简介 8.5.2 选择排序算法 8.5.3 好好学习&#xff0c;天天向上 8.5.1 排序算法简介 所谓排序&#xff0c;是指将数据集合中的元素按从小到大的顺序进行排列&#xff0c;或按从大到小的顺序进行排列。前者称为升序排序&#xff0c;后者称为降序排序。在数…...

JavaEE初阶第四期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(二)

专栏&#xff1a;JavaEE初阶起飞计划 个人主页&#xff1a;手握风云 目录 一、Thread类及常用方法 2.1. Thread的常见构造方法 2.2. Thread的常见属性 2.3. 启动一个线程 2.4. 中断一个线程 2.5. 等待一个线程 2.6. 休眠当前线程 一、Thread类及常用方法 2.1. Thread的…...

Metasploit常用命令详解

一、Metasploit 概述 Metasploit是一款开源的渗透测试框架&#xff0c;由 H.D. Moore 于 2003 年首次发布&#xff0c;目前由 rapid7 公司维护。它整合了大量漏洞利用模块、后渗透工具和漏洞扫描功能&#xff0c;已成为网络安全工程师、红队 / 蓝队成员及安全研究人员的核心工…...

2025.6.24总结

今天发生了两件事&#xff0c;这每件事情都足以影响我的工作状态。 1.团队中有人要转岗 这算是最让我有些小震惊的事件了。我不明白&#xff0c;那个同事干得好好的&#xff0c;为啥会转岗&#xff0c;为啥会被调到其他团队。虽然团队有正编&#xff0c;有od,但我自始自终觉得…...

2023年全国青少年信息素养大赛Python 复赛真题——玩石头游戏

今日python每日练习题为——玩石头游戏&#xff0c;大家记得坚持刷题哦&#xff0c;闯入国赛~ 每轮可拿 1-3 块石头&#xff0c;双方均采取最优策略。若石头数 n 为 4 的倍数&#xff0c;无论先手取 k 块&#xff08;1≤k≤3&#xff09;&#xff0c;后手总能取 4-k 块&#xf…...

MySQL之SQL性能优化策略

MySQL之SQL性能优化策略 一、主键优化策略1.1 主键的核心作用1.2 主键设计原则1.3 主键优化实践 二、ORDER BY优化策略2.1 ORDER BY执行原理2.2 ORDER BY优化技巧2.3 处理大结果集排序 三、GROUP BY优化策略3.1 GROUP BY执行原理3.2 GROUP BY优化方法 四、LIMIT优化策略4.1 LIM…...

AI时代工具:AIGC导航——AI工具集合

大家好!AIGC导航是一个汇集多种AIGC工具的平台&#xff0c;提供了丰富的工具和资源。 工具功能​: 该平台整合了多样的AIGC工具&#xff0c;涵盖了绘画创作、写作辅助以及视频制作等多个领域。绘画工具能够生成高质量的图像作品&#xff1b;写作工具支持从构思到润色的全流程写…...

性能测试-jmeter实战4

课程&#xff1a;B站大学 记录软件测试-性能测试学习历程、掌握前端性能测试、后端性能测试、服务端性能测试的你才是一个专业的软件测试工程师 性能测试-jmeter实战4 jmeter环境搭建1. 安装Java环境&#xff08;必需&#xff09; JMeter环境搭建完整指南1. 安装Java&#xff0…...

C++字符串的行输入

1、字符串的输入 下面用一个真实的示例来进行演示&#xff1a; #include<iostream> #include<string>int main() {using namespace std;const int ArSize 20;char name[ArSize];char dessert[ArSize];cout << "Enter your name:\n";cin >>…...

【Linux网络与网络编程】15.DNS与ICMP协议

1. DNS 1.1 DNS介绍 TCP/IP 中使用 IP 地址和端口号来确定网络上的一台主机的一个程序&#xff0c;但是 IP 地址不方便记忆&#xff0c;于是人们发明了一种叫主机名的字符串&#xff0c;并使用 hosts 文件来描述主机名和 IP 地址的关系。最初, 通过互连网信息中心(SRI-NIC)来…...

Python训练营-Day40-训练和测试的规范写法

1.单通道图片训练 # import torch # import torch.nn as nn # import torch.optim as optim # from torchvision import datasets, transforms # from torch.utils.data import DataLoader # import matplotlib.pyplot as plt # import numpy as np# # 设置中文字体支持 # plt…...

【Python-Day 29】万物皆对象:详解 Python 类的定义、实例化与 `__init__` 方法

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

内存泄漏和内存溢出的区别

内存泄漏&#xff08;Memory Leak&#xff09;和内存溢出&#xff08;Memory Overflow / Out Of Memory, OOM&#xff09;是软件开发中两个密切相关但又本质不同的内存问题&#xff1a; 核心区别一句话概括&#xff1a; 内存泄漏&#xff1a; 有垃圾对象占用内存却无法被回收&…...

Linux系统---Nginx配置nginx状态统计

配置Nignx状态统计 1、下载vts模块 https://github.com/vozlt/nginx-module-vts [rootclient ~]# nginx -s stop [rootclient ~]# ls anaconda-ks.cfg nginx-1.27.3 ceph-release-1-1.el7.noarch.rpm nginx-1.27.3.tar.gz info.sh …...

linux操作系统的软件架构分析

一、linux操作系统的层次结构 1.内核的主要功能 1&#xff09;进程管理 2&#xff09;内存管理 3&#xff09;文件系统 4&#xff09;进程间通信、I/O系统、网络通信协议等 2.系统程序 1&#xff09;系统接口函数库&#xff0c;比如libc 2)shell程序 3&#xff09;编译器、编辑…...

快速手搓一个MCP服务指南(三):FastMCP的核心组件-构建MCP服务的关键技术实现

FastMCP 是一套面向 LLM 应用开发的工具框架&#xff0c;通过标准化协议衔接大语言模型与外部功能组件&#xff0c;构建「LLM工具」的闭环交互体系。其核心技术体系包含四大模块&#xff1a;工具系统将 Python 函数转化为 LLM 可调用的能力单元&#xff0c;通过类型注解实现参数…...

创建首个 Spring Boot 登录项目

&#x1f4cc; 摘要 在 Java Web 开发中&#xff0c;登录功能是最基础也是最重要的模块之一。本文将手把手带你使用 IntelliJ IDEA 和 Maven 构建一个基于 Spring Boot 的简单登录系统&#xff0c;涵盖&#xff1a; 使用 IDEA 创建 Spring Boot 项目配置 Maven 依赖&#xff…...

order、sort、distribute和cluster by(Spark/Hive)

1. abstract ORDER BY&#xff1a;完整查询结果的全局行排序。与SORT BY、CLUSTER BY、DISTRIBUTE BY互斥&#xff0c;不能同时使用。 示例SELECT * FROM table_name ORDER BY column_name;SORT BY&#xff1a;只在每个分区内排序&#xff0c;局部排序结果不是全局有序。与ORD…...

# Python中等于号的使用

# Python中等于号的使用 ## 1. 问题的分析与思考 在Python中&#xff0c;等于号&#xff08;&#xff09;是一个赋值运算符&#xff0c;用于将右侧的值或表达式的结果赋给左侧的变量。这是Python&#xff08;以及许多其他编程语言&#xff09;中非常基础且核心的一个概念。理…...

无人机神经网络模块运行与技术难点

一、神经网络模块的运行方式 1. 分层处理架构 感知层 多模态数据融合&#xff1a;通过八元数卷积网络&#xff08;OCNN&#xff09;统一处理LiDAR、摄像头、IMU等异构传感器数据&#xff0c;将点云坐标&#xff08;x/y/z&#xff09;、图像RGB与光流信息编码至8维虚部&#…...

宝塔服务器调优工具 1.1(Opcache优化)

第一步&#xff1a;宝塔服务器调优工具 1.1&#xff08;按照下面的参数填写&#xff09; 第二步&#xff1a;路径/www/server/php/80/etc/php.ini 搜索jit jit1235 其中1235根据服务器情况修改 第三步&#xff1a;路径/www/server/php/80/etc/php-cli.ini 搜索 jit1235 其中…...

day041-web集群架构搭建

文章目录 0. 老男孩思想-高薪四板斧1. web集群架构图2. 搭建异地备份服务2.1 服务端-阿里云服务器2.1.1 查看rsync软件包2.1.2 添加rsync配置文件2.1.3 添加虚拟用户2.1.4 创建校验用户密码文件2.1.5 创建备份目录2.1.6 启动服务2.1.7 开放安全组端口2.1.8 发送检查邮件 2.2 客…...

国产化条码类库Spire.Barcode教程:如何使用 C# 读取 PDF 中的条码(两种方法轻松实现)

在 PDF 文档的 .NET 平台处理流程中&#xff0c;使用 C# 读取 PDF 条码 是一项常见需求&#xff0c;特别适用于处理扫描件或电子表单。无论是物流、金融、医疗还是制造行业&#xff0c;PDF 文档中经常包含用于追踪或识别的条码。这些条码可能是嵌入图像&#xff0c;也可能是矢量…...

vue 3 计算器

效果&#xff1a; <template><div class"calculator-container"><div class"calculator"><!-- 显示区域 --><div class"display">{{ formattedDisplay }}</div><!-- 按钮区域 --><div class"…...

CRMEB PHP多门店版v3.2.1系统全开源+Uniapp前端+搭建教程

一.介绍 CRMEB多店版是一款为品牌连锁门店打造的私域电商解决方案&#xff0c;以三大运营模式为核心&#xff0c;助力品牌连锁门店轻松构建全渠道、一体化的私域电商生态&#xff0c;促进“线上电商”与“线下门店”销售运营融合&#xff0c;加速品牌数字化转型&#xff0c;为…...

主机复制文字和文件到 Ubuntu 虚拟机

在 VMware Workstation Pro 16 中复制文字和文件到 Ubuntu 虚拟机&#xff0c;方法如下&#xff1a; Open-VM-Tools 禁用 Wayland 解决 。 1.安装 VMware Tools&#xff08;推荐&#xff09;或 open-vm-tools&#xff1a; sudo apt update sudo apt install open-vm-tools…...

性能测试 —— 数据库的连接池和主从同步和分表分区

一、数据库的调优&#xff08;库层面&#xff09; 1、数据库连接池 1、介绍&#xff1a;数据库连接池(Database Connection Pool)是一种用于管理数据库连接的技术&#xff0c;它通过预先创建并维护一组数据库连接来提高应用程序的性能和可扩展性。 2、创建、管理、关闭 数据…...

猿人学js逆向比赛第一届第十二题

一、分析请求 看到这里只有一个m的密文参数&#xff0c;没有cookie&#xff0c;请求头等其他的参数&#xff0c;那么这里跟一堆栈信息。 很顺利地锁定了m的加密位置。看到是字符串拼接然后使用btoa函数进行编码&#xff0c;那么这里尝试使用Python复现一下。顺利拿到结果。 复现…...

第十节 新特性与趋势-CSS层叠规则升级

以下是关于 ​​CSS层叠规则升级​​ 的全面解析&#xff0c;结合最新规范&#xff08;如级联层layer&#xff09;和传统层叠机制的演进&#xff0c;从核心原理、应用场景到实践策略的系统性总结&#xff1a; 一、传统层叠规则的三大支柱 CSS层叠规则的传统机制基于以下三个维…...

关键领域软件工厂的安全中枢如何全面升级供应链检测能力

随着软件供应链安全体系在互联网、金融等领域逐步成熟&#xff0c;关键领域正加速迈向以 MLOps、软件工厂为核心的新型研发生态。在这一过程中&#xff0c;面对代码安全、依赖合规、系统可信等多重挑战&#xff0c;传统人工审查模式已难以满足国家级高安全性要求。 Gitee Scan…...

西门子G120XA变频器:数据中心能效革命的核心引擎

在数字经济爆发式增长的今天&#xff0c;数据中心已成为支撑社会运转的"数字心脏"。然而&#xff0c;其庞大的能耗需求与绿色低碳目标之间的矛盾日益凸显——尤其是冷却系统作为数据中心第二大能耗单元&#xff08;占比约35%&#xff09;&#xff0c;正成为能效提升的…...

从零开始学习Spring Cloud Alibaba (一)

人狠话不多,直接开始少点屁话本着共同学习进步的目的和大家交流如有不对的地方望铁子们多多谅解 准备工具 开发工具 idea Java环境 jdk17 容器: docker Maven 3.8.6 仓库镜像阿里云 <mirror><id>alimaven</id><name>aliyun maven</name><…...

【C/C++】C++ 编程规范:101条规则准则与最佳实践

C 编程规范&#xff1a;101条规则准则与最佳实践 引言 C 是一门强大而复杂的语言&#xff0c;能高效控制硬件&#xff0c;也能写出优雅抽象。然而&#xff0c;正因其复杂性&#xff0c;项目中若缺乏统一规范&#xff0c;极易陷入混乱、难维护、易出错的泥潭。 本文总结了 10…...

PyTorch topk() 用法详解:取最大值

torch.topk(input, k) 返回张量中最大的 k 个元素以及它们在原张量中的 索引。 函数原型 torch.topk(input, k, dimNone, largestTrue, sortedTrue)参数说明&#xff1a; 参数说明input输入张量k要取出的前 k 个值dim指定沿哪个维度取值&#xff08;默认是最后一维&#xff…...

毕业论文查重原理及降重方法

【30%的重复率有那么重要吗&#xff1f;】 老师说论文重读率必须低于30%&#xff0c;否则无法毕业&#xff01; 如果您在专科或者普通本科学生&#xff0c;我只能这样一句话告诉你&#xff1a;你想多了~&#xff0c; 真的想多了~~~&#xff0c;一篇论文还不至于让你不能毕…...

Golang Kratos 系列:业务分层的若干思考(二)

上一篇文章简单讨论了领域层在Kratos中的使用&#xff0c;主要涉及引入领域层&#xff0c;将数据层和业务层之间的解耦&#xff0c;接下来讨论一个稍微全面一点的例子&#xff0c;在此基础上引入外部Api&#xff08;主要是易变部分&#xff09;的领域层下的情况。 我们同样可以…...

技术伦理之争:OpenAI陷抄袭风波,法院强制下架宣传视频

在AI巨头OpenAI宣布以65亿美元天价收购苹果前设计总监Jony Ive的硬件公司IO仅一个月后&#xff0c;一场抄袭指控将这家科技明星企业推上风口浪尖。 源自谷歌X实验室的初创企业IYO将OpenAI告上法庭&#xff0c;指控其窃取智能耳塞核心技术&#xff0c;并通过巨额收购试图掩盖抄袭…...

烟花爆竹生产企业库房存储安全风险预警系统

烟花爆竹生产企业库房存储安全风险预警系统是保障库房物资安全、规范作业流程、防范安全事故的重要技术手段&#xff0c;涵盖多个关键预警功能。​ 温湿度预警​ 在库房内安装温湿度传感器&#xff0c;这些传感器如同敏锐的“环境感知员”&#xff0c;能够实时监测库房内环境变…...

Jenkins+Jmeter+Ant接口持续集成

2025最新Jmeter接口测试从入门到精通&#xff08;全套项目实战教程&#xff09; 前言&#xff1a; 为什么要用Jmeter做接口测试&#xff1a; 当选择这套方案的时候&#xff0c;很多人会问&#xff0c;为什么选择Jmeter做Case管理&#xff1f;为什么不自己写框架&#xff1f;说…...

基于STM32的寻迹小车设计

标题:基于STM32的寻迹小车设计 内容:1.摘要 本文围绕基于STM32的寻迹小车设计展开。背景是随着自动化技术的发展&#xff0c;寻迹小车在工业巡检、物流运输等领域有广泛应用前景。目的是设计一款能稳定、准确寻迹的小车。方法上&#xff0c;以STM32微控制器为核心&#xff0c;…...

【150】基于SSM+Vue实现的小说阅读小程序(有文档)

系统介绍 基于SSMVue实现的小说阅读小程序采用前后端分离的架构方式&#xff0c;系统设计了管理员、用户两种角色&#xff0c;系统分为管理端、小程序端&#xff0c;管理端实现了管理员登录、个人中心、管理员管理、帮助中心管理、基础数据管理、论坛中心管理、公告资讯管理、…...

ValKey中使用SIMD指令优化bitcount命令

一、AVX/AVX2 的历史演进 随着计算机技术的飞速发展&#xff0c;数据处理需求呈指数级增长&#xff0c;SIMD&#xff08;单指令多数据&#xff09;技术应运而生。它通过一条指令同时处理多个数据元素&#xff0c;大幅提升计算效率&#xff0c;从早期的 MMX 技术起步&#xff0…...

leetcode114-二叉树展开为链表

leetcode 114 思路 用简单例子推导规律 不要一开始就看复杂的树&#xff0c;先从最简单的情况入手 案例一&#xff1a;只有一个节点 输入&#xff1a;1 输出&#xff1a;1不需要任何操作&#xff0c;直接返回 案例二&#xff1a;有两个节点 输入&#xff1a; 1/2输出&a…...

第七章 习题

1.给出下面表达式的逆波兰表示(后缀式): 3请将表达式-(ab)* (cd)-(abc)分别表示成三元式,间接三元式和四元式序列 四元式(Op,arg1,arg2,result) (,a,b,T1) (,c,d,T2) (*,T1,T2,T3) (uminus,T3,-,T4) (,a,b,T5) (,T5,c,T6) (-,T4,T6,r) 三元式 (op,arg1,arg2) (0) (,…...