AI生成的一个.netcore 经典后端架构

news/2024/12/5 1:07:14/

下面是一个完整的 .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 System.Threading.Tasks;
using Oracle.ManagedDataAccess.Client;public class StudentRepository
{private readonly string _connectionString;public StudentRepository(string connectionString){_connectionString = connectionString;}public async Task<List<Student>> GetAllStudentsAsync(){using (var connection = new OracleConnection(_connectionString)){return (await connection.QueryAsync<Student>("SELECT * FROM Students")).ToList();}}public async Task<List<Student>> GetPagedStudentsAsync(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 (await connection.QueryAsync<Student>(sql, new { offset, pageSize })).ToList();}}public async Task<Student> GetStudentByIdAsync(int id){using (var connection = new OracleConnection(_connectionString)){return await connection.QueryFirstOrDefaultAsync<Student>("SELECT * FROM Students WHERE Id = :id", new { id });}}public async Task AddStudentAsync(Student student){using (var connection = new OracleConnection(_connectionString)){await connection.ExecuteAsync("INSERT INTO Students (ClassId, Name) VALUES (:classId, :name)", new { student.ClassId, student.Name });}}public async Task UpdateStudentAsync(Student student){using (var connection = new OracleConnection(_connectionString)){await connection.ExecuteAsync("UPDATE Students SET ClassId = :classId, Name = :name WHERE Id = :id", new { student.ClassId, student.Name, student.Id });}}public async Task DeleteStudentAsync(int id){using (var connection = new OracleConnection(_connectionString)){await connection.ExecuteAsync("DELETE FROM Students WHERE Id = :id", new { id });}}public async Task<List<StudentGradeDTO>> GetStudentGradesByClassIdAsync(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 (await connection.QueryAsync<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 _repository.GetAllStudentsAsync();}public async Task<List<Student>> GetPagedStudentsAsync(int page, int pageSize){return await _pagedStudentCache.GetOrAddAsync((page, pageSize), async key => await _repository.GetPagedStudentsAsync(key.Page, key.PageSize));}public async Task<Student> GetStudentByIdAsync(int id){return await _studentCache.GetOrAddAsync(id, async key => await _repository.GetStudentByIdAsync(key));}public async Task AddStudentAsync(Student student){await _repository.AddStudentAsync(student);}public async Task UpdateStudentAsync(Student student){await _repository.UpdateStudentAsync(student);}public async Task DeleteStudentAsync(int id){await _repository.DeleteStudentAsync(id);}public async Task<List<StudentGradeDTO>> GetStudentGradesByClassIdAsync(int classId){return await _studentGradesCache.GetOrAddAsync(classId, async key => await _repository.GetStudentGradesByClassIdAsync(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){await _service.AddStudentAsync(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();}await _service.UpdateStudentAsync(student);return NoContent();}[HttpDelete("{id}")]public async Task<IActionResult> DeleteStudentAsync(int id){await _service.DeleteStudentAsync(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 数据库,并实现了学生表、课程表、成绩表和班级表的基本增删改查功能,以及查询某个班级学生成绩的功能。查询功能使用了自定义缓存来优化性能,所有数据访问操作都使用了异步方式。希望这些代码对你有所帮助!


http://www.ppmy.cn/news/1552426.html

相关文章

ORB-SLAM2 ----- LocalMapping::ComputeF12和ORBmatcher::CheckDistEpipolarLine

文章目录 一、函数意义二、LocalMapping::ComputeF12()1.函数讲解2.函数代码 三、ORBmatcher::CheckDistEpipolarLine()1.函数讲解2.函数代码 四、总结 一、函数意义 这两个函数在LocalMapping::CreateNewMapPoints()被调用&#xff0c;之所以单独拿出来讲&#xff0c;是因为这…

【WEB开发.js】HTTP请求和相应报文的头字段:Content-Type (巨巨巨巨详细好懂的举例详解)

Content-Type 是 HTTP 请求和响应报文中的头字段之一&#xff0c;用于指定发送的数据类型&#xff08;MIME 类型&#xff09;。它告诉服务器或客户端数据的格式&#xff0c;方便接收方正确解析和处理内容。 例如&#xff0c;在发送 JSON 数据时&#xff0c;会指定 Content-Typ…

[RabbitMQ] 延迟队列+事务+消息分发

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

无人机主控芯片技术与算法详解!

一、无人机主控芯片核心技术 高性能CPU&#xff1a; 无人机需要高性能的CPU来处理复杂的飞行控制算法、图像处理和数据传输等任务。目前&#xff0c;无人机的CPU主要有大疆自研的飞控系统、高通提供的无人机设计平台Snapdragon Flight&#xff0c;以及基于开源平台APM、Px4等…

HCIA笔记6--路由基础与静态路由:浮动路由、缺省路由、迭代查找

文章目录 0. 概念1.路由器工作原理2. 跨网访问流程3. 静态路由配置4. 静态路由的应用场景4.1 路由备份4.2 浮动路由4.3 缺省路由 5. 迭代路由6 问题6.1 为什么路由表中有的下一跳的地址有接口&#xff1f;6.2 个人电脑的网关本质是什么&#xff1f; 0. 概念 自治系统&#xff…

故障诊断 | Transformer-LSTM组合模型的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | Transformer-LSTM组合模型的故障诊断(Matlab) 源码设计 %% 初始化 clear close all clc disp(此程序务必用2023b及其以上版本的MATLAB!否则会报错!) warning off %

【iOS】设计模式的六大原则

【iOS】设计模式的六大原则 文章目录 【iOS】设计模式的六大原则前言开闭原则——OCP单一职能原则——SRP里氏替换原则——LSP依赖倒置原则——DLP接口隔离原则——ISP迪米特法则——LoD小结 前言 笔者这段时间看了一下有关于设计模式的七大原则&#xff0c;下面代码示例均为OC…

【Oracle11g SQL详解】INSERT INTO 的用法及插入数据注意事项

INSERT INTO 的用法及插入数据注意事项 在 Oracle 11g 中&#xff0c;INSERT INTO 语句用于向表中插入数据&#xff0c;是数据写入操作中最常用的 SQL 语句之一。本文将详细介绍 INSERT INTO 的基本语法、常见场景、注意事项及常见错误处理。 一、INSERT INTO 的基本语法 INS…