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

csharp 复制代码
public class Student
{
    public int Id { get; set; }
    public int ClassId { get; set; }
    public string Name { get; set; }
}

Models/Course.cs

csharp 复制代码
public class Course
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Models/Grade.cs

csharp 复制代码
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

csharp 复制代码
public class Class
{
    public int Id { get; set; }
    public string Name { get; set; }
}

数据传输对象

为了优化网络传输,我们通常不会直接返回实体模型,而是使用DTO。

DTOs/StudentGradeDTO.cs

csharp 复制代码
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

csharp 复制代码
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

csharp 复制代码
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.Score
                        FROM Students s
                        JOIN Grades g ON s.Id = g.StudentId
                        JOIN Courses c ON g.CourseId = c.Id
                        WHERE s.ClassId = :classId";

            return connection.Query<StudentGradeDTO>(sql, new { classId }).ToList();
        }
    }
}

服务层

服务层处理业务逻辑,调用仓库层的方法来完成具体的功能,并集成缓存逻辑。

Services/StudentService.cs

csharp 复制代码
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

csharp 复制代码
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

csharp 复制代码
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

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

csharp 复制代码
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 数据库,并实现了学生表、课程表、成绩表和班级表的基本增删改查功能,以及查询某个班级学生成绩的功能。查询功能使用了自定义缓存来优化性能。希望这些代码对你有所帮助!

相关推荐
安思派Anspire44 分钟前
LangGraph + MCP + Ollama:构建强大代理 AI 的关键(一)
前端·深度学习·架构
radient2 小时前
Golang-GMP 万字洗髓经
后端·架构
Code季风2 小时前
Gin Web 层集成 Viper 配置文件和 Zap 日志文件指南(下)
前端·微服务·架构·go·gin
鹏程十八少2 小时前
9.Android 设计模式 模板方法 在项目中的实战
架构
程序员JerrySUN4 小时前
RK3588 Android SDK 实战全解析 —— 架构、原理与开发关键点
android·架构
ai小鬼头15 小时前
AIStarter如何助力用户与创作者?Stable Diffusion一键管理教程!
后端·架构·github
掘金-我是哪吒17 小时前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
国服第二切图仔17 小时前
文心开源大模型ERNIE-4.5-0.3B-Paddle私有化部署保姆级教程及技术架构探索
百度·架构·开源·文心大模型·paddle·gitcode
SelectDB18 小时前
SelectDB 在 AWS Graviton ARM 架构下相比 x86 实现 36% 性价比提升
大数据·架构·aws
weixin_4373982119 小时前
转Go学习笔记(2)进阶
服务器·笔记·后端·学习·架构·golang