AI生成的一个.netcore 经典后端架构
下面是一个完整的 .NET Core 后端项目示例,使用 Dapper 作为轻量级 ORM 访问 Oracle 数据库,并实现高性能架构。我们将实现学生表、课程表、成绩表和班级表的基本增删改查功能,以及查询某个班级学生成绩的功能,并使用自定义缓存来优化查询性能。
项目结构
MyApp/
│── Controllers/ # 控制器层,处理HTTP请求
│ └── StudentController.cs
│── Models/ # 模型层,定义实体类
│ ├── Student.cs
│ ├── Course.cs
│ ├── Grade.cs
│ └── Class.cs
│── DTOs/ # 数据传输对象,用于API响应
│ └── StudentGradeDTO.cs
│── Services/ # 服务层,业务逻辑处理
│ └── StudentService.cs
│── Repositories/ # 仓库层,数据访问
│ └── StudentRepository.cs
│── Cache/ # 缓存层
│ └── InMemoryCache.cs
│── Startup.cs # 应用启动配置
│── appsettings.json # 应用配置文件
└── Program.cs # 应用入口
实体模型
首先定义实体模型,这些模型代表数据库中的表。
Models/Student.cs
public class Student
{public int Id { get; set; }public int ClassId { get; set; }public string Name { get; set; }
}
Models/Course.cs
public class Course
{public int Id { get; set; }public string Name { get; set; }
}
Models/Grade.cs
public class Grade
{public int Id { get; set; }public int StudentId { get; set; }public int CourseId { get; set; }public decimal Score { get; set; }
}
Models/Class.cs
public class Class
{public int Id { get; set; }public string Name { get; set; }
}
数据传输对象
为了优化网络传输,我们通常不会直接返回实体模型,而是使用DTO。
DTOs/StudentGradeDTO.cs
public class StudentGradeDTO
{public int StudentId { get; set; }public string StudentName { get; set; }public string CourseName { get; set; }public decimal Score { get; set; }
}
缓存层
我们使用一个简单的字典来实现内存缓存。
Cache/InMemoryCache.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;public class InMemoryCache<TKey, TValue>
{private readonly Dictionary<TKey, CacheEntry<TValue>> _cache = new Dictionary<TKey, CacheEntry<TValue>>();public async Task<TValue> GetOrAddAsync(TKey key, Func<TKey, Task<TValue>> valueFactory, TimeSpan? expiration = null){if (_cache.TryGetValue(key, out var cacheEntry)){if (cacheEntry.Expiration > DateTime.UtcNow){return cacheEntry.Value;}else{_cache.Remove(key);}}var value = await valueFactory(key);_cache[key] = new CacheEntry<TValue> { Value = value, Expiration = DateTime.UtcNow + (expiration ?? TimeSpan.FromMinutes(5)) };return value;}private class CacheEntry<T>{public T Value { get; set; }public DateTime Expiration { get; set; }}
}
仓库层
仓库层负责与数据库交互,执行具体的SQL命令。
Repositories/StudentRepository.cs
using Dapper;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Oracle.ManagedDataAccess.Client;public class StudentRepository
{private readonly string _connectionString;public StudentRepository(string connectionString){_connectionString = connectionString;}public List<Student> GetAllStudents(){using (var connection = new OracleConnection(_connectionString)){return connection.Query<Student>("SELECT * FROM Students").ToList();}}public List<Student> GetPagedStudents(int page, int pageSize){using (var connection = new OracleConnection(_connectionString)){int offset = (page - 1) * pageSize;var sql = $"SELECT * FROM Students ORDER BY Id OFFSET :offset ROWS FETCH NEXT :pageSize ROWS ONLY";return connection.Query<Student>(sql, new { offset, pageSize }).ToList();}}public Student GetStudentById(int id){using (var connection = new OracleConnection(_connectionString)){return connection.QueryFirstOrDefault<Student>("SELECT * FROM Students WHERE Id = :id", new { id });}}public void AddStudent(Student student){using (var connection = new OracleConnection(_connectionString)){connection.Execute("INSERT INTO Students (ClassId, Name) VALUES (:classId, :name)", new { student.ClassId, student.Name });}}public void UpdateStudent(Student student){using (var connection = new OracleConnection(_connectionString)){connection.Execute("UPDATE Students SET ClassId = :classId, Name = :name WHERE Id = :id", new { student.ClassId, student.Name, student.Id });}}public void DeleteStudent(int id){using (var connection = new OracleConnection(_connectionString)){connection.Execute("DELETE FROM Students WHERE Id = :id", new { id });}}public List<StudentGradeDTO> GetStudentGradesByClassId(int classId){using (var connection = new OracleConnection(_connectionString)){var sql = @"SELECT s.Id AS StudentId, s.Name AS StudentName, c.Name AS CourseName, g.ScoreFROM Students sJOIN Grades g ON s.Id = g.StudentIdJOIN Courses c ON g.CourseId = c.IdWHERE s.ClassId = :classId";return connection.Query<StudentGradeDTO>(sql, new { classId }).ToList();}}
}
服务层
服务层处理业务逻辑,调用仓库层的方法来完成具体的功能,并集成缓存逻辑。
Services/StudentService.cs
using System.Collections.Generic;
using System.Threading.Tasks;public class StudentService
{private readonly StudentRepository _repository;private readonly InMemoryCache<int, Student> _studentCache;private readonly InMemoryCache<(int Page, int PageSize), List<Student>> _pagedStudentCache;private readonly InMemoryCache<int, List<StudentGradeDTO>> _studentGradesCache;public StudentService(StudentRepository repository){_repository = repository;_studentCache = new InMemoryCache<int, Student>();_pagedStudentCache = new InMemoryCache<(int Page, int PageSize), List<Student>>();_studentGradesCache = new InMemoryCache<int, List<StudentGradeDTO>>();}public async Task<List<Student>> GetAllStudentsAsync(){return await Task.FromResult(_repository.GetAllStudents());}public async Task<List<Student>> GetPagedStudentsAsync(int page, int pageSize){return await _pagedStudentCache.GetOrAddAsync((page, pageSize), async key => await Task.FromResult(_repository.GetPagedStudents(key.Page, key.PageSize)));}public async Task<Student> GetStudentByIdAsync(int id){return await _studentCache.GetOrAddAsync(id, async key => await Task.FromResult(_repository.GetStudentById(key)));}public void AddStudent(Student student){_repository.AddStudent(student);}public void UpdateStudent(Student student){_repository.UpdateStudent(student);}public void DeleteStudent(int id){_repository.DeleteStudent(id);}public async Task<List<StudentGradeDTO>> GetStudentGradesByClassIdAsync(int classId){return await _studentGradesCache.GetOrAddAsync(classId, async key => await Task.FromResult(_repository.GetStudentGradesByClassId(key)));}
}
控制层
控制层接收客户端请求,并调用服务层提供的方法来处理请求。
Controllers/StudentController.cs
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;[ApiController]
[Route("api/[controller]")]
public class StudentController : ControllerBase
{private readonly StudentService _service;public StudentController(StudentService service){_service = service;}[HttpGet]public async Task<ActionResult<List<Student>>> GetAllStudentsAsync(){return Ok(await _service.GetAllStudentsAsync());}[HttpGet("paged")]public async Task<ActionResult<List<Student>>> GetPagedStudentsAsync(int page = 1, int pageSize = 10){return Ok(await _service.GetPagedStudentsAsync(page, pageSize));}[HttpGet("{id}")]public async Task<ActionResult<Student>> GetStudentByIdAsync(int id){var student = await _service.GetStudentByIdAsync(id);if (student == null){return NotFound();}return Ok(student);}[HttpPost]public async Task<ActionResult<Student>> AddStudentAsync([FromBody] Student student){_service.AddStudent(student);return CreatedAtAction(nameof(GetStudentByIdAsync), new { id = student.Id }, student);}[HttpPut("{id}")]public async Task<IActionResult> UpdateStudentAsync(int id, [FromBody] Student student){if (id != student.Id){return BadRequest();}_service.UpdateStudent(student);return NoContent();}[HttpDelete("{id}")]public async Task<IActionResult> DeleteStudentAsync(int id){_service.DeleteStudent(id);return NoContent();}[HttpGet("class/{classId}/grades")]public async Task<ActionResult<List<StudentGradeDTO>>> GetStudentGradesByClassIdAsync(int classId){return Ok(await _service.GetStudentGradesByClassIdAsync(classId));}
}
配置依赖注入
在Startup.cs
中配置依赖注入,以便可以在控制器和服务之间共享仓库实例。
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MyApp.Repositories;
using MyApp.Services;public class Startup
{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }public void ConfigureServices(IServiceCollection services){services.AddControllers();services.AddScoped<StudentRepository>(provider => new StudentRepository(Configuration.GetConnectionString("DefaultConnection")));services.AddScoped<StudentService>();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}
}
配置文件
在appsettings.json
中配置数据库连接字符串。
appsettings.json
{"ConnectionStrings": {"DefaultConnection": "User Id=your_username;Password=your_password;Data Source=your_data_source;"},"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*"
}
应用入口
Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;public class Program
{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});
}
总结
通过上述代码,我们实现了一个高性能的 .NET Core 后端项目,使用 Dapper 访问 Oracle 数据库,并实现了学生表、课程表、成绩表和班级表的基本增删改查功能,以及查询某个班级学生成绩的功能。查询功能使用了自定义缓存来优化性能。希望这些代码对你有所帮助!
相关文章:
AI生成的一个.netcore 经典后端架构
下面是一个完整的 .NET Core 后端项目示例,使用 Dapper 作为轻量级 ORM 访问 Oracle 数据库,并实现高性能架构。我们将实现学生表、课程表、成绩表和班级表的基本增删改查功能,以及查询某个班级学生成绩的功能,并使用自定义缓存来…...
深度学习-48-AI应用实战之基于face_recognition的人脸识别
文章目录 1 人脸识别1.1 识别原理1.2 应用场景2 python实现人脸识别2.1 windows安装face_recognition2.2 安装问题及解决3 使用示例3.1 人脸区域检测3.2 对齐与编码3.3 人脸匹配3.4 信息录入4 附录4.1 函数cv2.rectangle4.2 参考附录1 人脸识别 通过图片或者摄像头的方式,将识…...
【Rabbitmq篇】高级特性----事务,消息分发
目录 事务 消息分发 应用场景 1. 限流 2.负载均衡 事务 RabbitMQ是基于AMQP协议实现的,该协议实现了事务机制,因此RabbitMQ也支持事务机制.SpringAMQP也提供了对事务相关的操作.RabbitMQ事务允许开发者确保消息的发送和接收是原子性的,要么全部成功,要么全部失败. 何为原…...
Python进程和线程适用场景
在选择使用 进程(Process)和 线程(Thread)时,通常取决于任务的类型、程序的需求以及硬件资源的限制。进程和线程各自有不同的特点,适用于不同的场景。下面是关于进程和线程的一些常见应用场景和选择指导&am…...
flutter开发环境—Windows
一、简介 我们使用最新版的flutter版本安装。 参考链接 名称地址官方网站https://flutter.dev/官方中文网站文档 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter软件下载路径https://docs.flutter.dev/release/archive?tabwindows 二、操作流程 2.1 下载软件 点…...
展示和添加篮球队信息--laravel与elementplus
之前使用laravel与inertia来做过一样的功能,感觉不满意,因此再结合elementplus重做一遍,先展示下重做后的效果。重写后的代码相比之下比较优雅。 球队首页 球队添加页 球员首页 很明显的改变,我新增了侧栏菜单来控制局部模块(这里是指NBABasketba…...
写一份客服网络安全意识培训PPT
一、为什么要对客服人员定期进行网络安全培训呢? 人员组成复杂:企业既有自由人员又有采购的外包公司客服,为了节约成本可能外包占大多数,这必然加强了人群的流动性所以往往得不到系统的培训。人员素质参差不齐:因为工…...
具体的技术和工具在县级融媒体建设3.0中有哪些应用?
以下是结合数据来看县级融媒体建设3.0的一些情况: 技术应用方面 大数据:人民网舆情数据中心执行主任董盟君提到,通过大数据分析可让融媒体单位快速关注聚焦点,实现智能策划、智能推送、智能传播,推动媒体传播影响力提…...
【uniapp】轮播图
前言 Uniapp的swiper组件是一个滑块视图容器组件,可以在其中放置多个轮播图或滑动卡片。它是基于微信小程序的swiper组件进行封装,可以在不同的平台上使用,如微信小程序、H5、App等。 效果图 前端代码 swiper组件 <template><vi…...
Rust编程语言代码详细运行、编译方法
以下是针对不同类型的 Rust 代码(以常见的命令行程序为例)详细的运行方法: 前提条件 在运行 Rust 代码之前,确保你已经在系统上安装了 Rust 编程语言环境。如果尚未安装,可以通过以下步骤进行安装: 访问…...
node.js基础学习-http模块-JSONP跨域传值(四)
前言 JSONP(JSON with Padding)是一种用于跨域数据传输的技术。在浏览器的同源策略限制下,一般情况下,JavaScript 不能直接从不同域的服务器获取数据。JSONP 通过利用 <script> 标签的跨域特性来绕过这个限制。 它本质上是一…...
Unity高效编程经验50条分享
1.避免频繁创建临时对象 错误写法:obj.transform.position pos;这种写法会在Lua中频繁返回transform对象导致gc正确写法:创建一个静态方法来设置位置,例如 class LuaUtil { static void SetPos(GameObject obj, float x, float y, float z)…...
TypeScript 泛型
在 TypeScript 中,泛型是一种强大的工具,它允许你在定义函数、类、接口或类型别名时不指定具体的类型。这意味着你可以为这些实体创建可重用的组件,这些组件可以在不同的类型上以一致的方式工作。今天,我们将深入探讨 TypeScript …...
【Java从入门到放弃 之 条件判断与循环】
条件判断与循环 条件判断if 语句if-else 语句if-else 嵌套语句switch 语句 循环for 循环while 循环do-while 循环break 和 continuebreak 关键字continue 关键字总结 条件判断 条件判断用于根据不同的条件执行不同的代码块。Java 中常用的条件判断语句有 if、if-else 和 switc…...
Ubuntu20.04安装kalibr
文章目录 环境配置安装wxPython下载编译测试报错1问题描述问题分析问题解决 参考 环境配置 Ubuntu20.04,python3.8.10,boost自带的1.71 sudo apt update sudo apt-get install python3-setuptools python3-rosinstall ipython3 libeigen3-dev libboost…...
Flink 任务启动脚本-V2(包括ck启动)
#!/bin/bash#crontab时设置,如果依赖其他环境变量配置,可以在脚本执行一下环境变量脚本 source /etc/profile# 进入脚本目录 curdirdirname "$0" curdircd "$curdir"; pwd echo "进入启动脚本目录 $curdir"# 定义应用程序…...
扫雷-完整源码(C语言实现)
云边有个稻草人-CSDN博客 在学完C语言函数之后,我们就有能力去实现简易版扫雷游戏了(成就感满满),下面是扫雷游戏的源码,快试一试效果如何吧! 在test.c里面进行扫雷游戏的测试,game.h和game.c…...
python -从文件夹批量提取pdf文章的第n页,并存储起来
python -从文件夹批量提取pdf文章的第n页,并存储起来 废话不多说,看下面代码 讲解一下下面代码 reader PyPDF2.PdfReader (file) 将文件转化为PdfReader 对象,方便使用内置方法。 first_page reader.pages[0] 提取第一页 writer PyPDF…...
R Excel 文件操作指南
R Excel 文件操作指南 概述 R 语言是一种强大的统计分析工具,广泛用于数据分析和可视化。在实际应用中,经常需要将 R 语言与 Excel 文件结合使用,以便处理和分析数据。本指南将介绍如何在 R 中读取、写入和操作 Excel 文件。 准备工作 在…...
RabbitMQ 安装延迟队列插件 rabbitmq_delayed_message_exchange
前言: RabbitMQ 延迟队列插件(rabbitmq_delayed_message_exchange)是一个社区开发的插件,它为 RabbitMQ 添加了支持延迟消息的功能。通过这个插件,用户可以创建一种特殊的交换机类型 x-delayed-message,该…...
fatal error in include chain (rtthread.h):rtconfig.h file not found
项目搜索这个文件 rtconfig 找到后将其复制粘贴到 你的目录\Keil\ARM\ARMCC\include 应该还有cJSON,rtthread.h和 等也复制粘贴下...
Java 反射(Reflection)
Java 反射(Reflection) Java 反射(Reflection)是一个强大的特性,它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力,这在很多框架和库中被广泛使用&#…...
Python爬取机车网车型数据并存入Mysql数据库
结果展示(文末附完整代码): 一、引言 在当今数字化时代,数据对于各个领域的重要性不言而喻。对于机车行业而言,获取丰富的机车品牌、车型及详细信息数据,能够为市场分析、消费者研究等提供有力支持。本文将…...
fpga 时序分析基础
目录 触发器的动态参数 同步时序电路分析 1. 时钟脉冲的特性 2. 同步时序电路分析 Timing Analyzer的应用 异步时序与亚稳态问题 时序分析就是对时序电路进行时序检查,通过分析电路中所有寄存器之间的路径延迟以检查电路的传输延迟是否会导致触发器的建立时间…...
python学习——二维列表的列表生成式
二维列表的列表生成式允许你生成一个列表,其中每个元素本身也是一个列表。这在处理矩阵或表格数据时非常有用。 以下是如何使用列表生成式来创建二维列表的示例: 文章目录 基本语法示例1. 创建一个 3x3 的单位矩阵2. 创建一个 4x4 的乘法表3. 创建一个 …...
【错误❌】——槽函数定义好但未初始化
public slots:void onClose(); 初始化即可成功:...
OpenCV相机标定与3D重建(6)将3D物体点投影到2D图像平面上函数projectPoints()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::fisheye::projectPoints 是 OpenCV 库中用于鱼眼镜头模型的函数,它将3D物体点投影到2D图像平面上。这个函数对于模拟或者理解鱼眼…...
【Linux】剧幕中的灵魂更迭:探索Shell下的程序替换
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出,万山无阻 目录 📖一、进程程序替换 1.替换的演示 ❓替换与执行流 ❓程序替换≠进程替换 2.替换的原理 …...
38 基于单片机的宠物喂食(ESP8266、红外、电机)
目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机,采用L298N驱动连接P2.3和P2.4口进行电机驱动, 然后串口连接P3.0和P3.1模拟ESP8266, 红外传感器连接ADC0832数模转换器连接单片机的P1.0~P1.…...
Unity中的数学应用 之 角色移动中单位化向量的妙用 (小学难度)
最近准备从简单到困难跟几个教程用以加强自己的业务能力,相信很多小伙伴都做过胡闹厨房这一个案例,其实这个案例比较初级,但是也包含了很多平常可能注意不到小细节,所以我就以它为举例,拓展其中的数学知识 CodeMonkey教…...
网络舆情分析师证书/seo免费入门教程
str str.replace(/,/g, "");...
如何创建微网站/网站推广工作
2019独角兽企业重金招聘Python工程师标准>>> Java8 BASE64编解码 Base64是一种用64个字符来表示任意二进制数据的方法。 Base64是一种最常见的二进制编码方法。 Java一直缺少BASE64编码 API,以至于通常在项目开发中会选用第三方的API实现。但…...
贵阳专用网站建设/郑州网站建设制作
文章目录Key is stored in legacy trusted.gpg keyring (/etc/apt/truste和apt update | upgrade; apt-key相关的配置文件都在目录/etc/apt下,共有以下内容:方法一:没成功,而且我的系统上显示采用的是第二种方式,没有用…...
个人装修队/武汉排名seo公司
这是一道区间贪心的题目,对于这道题,由于岛屿的位置在坐标轴上是确定的,而雷达的位置及数量则无法确定,因此我们可以根据岛屿来确定雷达的位置及数量。首先,我们可以根据岛屿的位置以及雷达的半径来确定覆盖该岛屿的雷…...
ui设计培训一般多久/嘉兴百度seo
2019独角兽企业重金招聘Python工程师标准>>> 当前日志系统常用的有elk(elasticsearch logstash kibana),不过很多公司不喜欢用logstash,而会用很多其他性能好、资源利用少的日志采集软件,其中rsyslog会是很…...
如何租用服务器做网站/长安seo排名优化培训
MPI简介在程序中,不同的进程需要相互的数据交换,特别是在科学计算中,需要大规模的计算与数据交换,集群可以很好解决单节点计算力不足的问题,但在集群中大规模的数据交换是很耗费时间的,因此需要一种在多节点…...