首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从零开始使用Blazor和.NET 9构建学生成绩管理系统

从零开始使用Blazor和.NET 9构建学生成绩管理系统

原创
作者头像
码事漫谈
发布2025-07-20 19:56:14
发布2025-07-20 19:56:14
3871
举报
文章被收录于专栏:程序员程序员
image.png
image.png

其实后端程序员也可以快速构建出拥有漂亮界面的UI。

本文将从零开始,使用Blazor Server.NET 9构建一个功能完善的学生成绩管理系统。我们将采用分层架构设计,结合最新的Bootstrap Blazor组件库,实现从数据建模到部署上线的完整开发流程。通过本文,您将掌握Blazor Server的核心开发技巧、EF Core 9.0的数据操作方法以及企业级应用的最佳实践。

一、需求分析

1.1 用户角色与功能需求

学生成绩管理系统需满足两类核心用户的需求:

角色

核心功能

权限控制

教师

成绩录入/修改、课程管理、统计分析

全部功能访问权限

学生

成绩查询、个人信息查看

仅查看本人数据

1.2 功能模块划分

系统采用模块化设计,包含以下关键模块:

  1. 学生管理:基础信息CRUD,支持批量导入导出
  2. 课程管理:课程信息维护与学生选课管理
  3. 成绩管理:成绩录入、修改、查询与统计分析
  4. 用户认证:基于角色的身份验证与授权

1.3 非功能需求

  • 性能:支持1000+学生数据的高效查询
  • 安全:密码加密存储,操作日志记录
  • 易用性:响应式设计,适配桌面/平板设备
  • 可扩展性:模块化架构,支持功能横向扩展

二、架构设计

2.1 技术栈选型

技术领域

选型

优势

前端框架

Blazor Server (.NET 9)

共享C#代码,实时双向绑定

UI组件库

Bootstrap Blazor v9.7.0

企业级UI组件,丰富的数据表格功能

数据访问

EF Core 9.0

强大的ORM,支持Code First开发

身份认证

ASP.NET Core Identity

完善的用户管理与授权机制

数据库

SQL Server LocalDB

开发便捷,生产环境可无缝迁移至SQL Server

2.2 分层架构设计

采用Clean Architecture思想,实现关注点分离:

代码语言:txt
复制
StudentGradeManagement/
├── Application/          # 应用服务层(业务逻辑)
├── Domain/               # 领域层(实体与接口)
├── Infrastructure/       # 基础设施层(数据访问、外部服务)
└── Web/                  # 表示层(Blazor UI)

各层职责

  • 领域层:定义核心实体(Student, Course, Grade)和仓储接口
  • 应用层:实现业务逻辑,协调领域对象
  • 基础设施层:提供EF Core数据访问实现、文件存储等
  • 表示层:Blazor组件与页面,处理用户交互

2.3 数据库设计

核心实体关系模型:

代码语言:mermaid
复制
erDiagram
    Student ||--o{ Grade : "has"
    Course ||--o{ Grade : "has"
    StudentCourse }|--|| Student : "enrolls"
    StudentCourse }|--|| Course : "includes"
    
    Student {
        int StudentId PK
        string Name
        string StudentNumber UK
        string Class
        string Email
    }
    
    Course {
        int CourseId PK
        string CourseName
        string CourseCode UK
        int Credits
    }
    
    Grade {
        int GradeId PK
        int StudentId FK
        int CourseId FK
        decimal Score
        string Remark
        DateTime CreatedAt
    }
    
    StudentCourse {
        int StudentId PK,FK
        int CourseId PK,FK
    }

三、环境搭建

3.1 开发环境准备

  1. 安装.NET 9 SDKundefined从微软官网下载并安装.NET 9 SDK,验证安装:dotnet --version # 应显示9.0.x
  2. 配置Visual Studio 2022undefined安装ASP.NET和Web开发工作负载,确保勾选:
    • .NET 9 SDK
    • Blazor Server开发工具
    • SQL Server LocalDB
  3. 创建Blazor Server项目undefined使用以下命令创建项目:dotnet new blazorserver -n StudentGradeManagement --framework net9.0 cd StudentGradeManagement

3.2 项目结构调整

按照分层架构重构项目结构:

代码语言:bash
复制
# 创建核心项目
dotnet new classlib -n Domain
dotnet new classlib -n Application
dotnet new classlib -n Infrastructure

# 添加项目引用
dotnet add Web reference Application
dotnet add Application reference Domain
dotnet add Infrastructure reference Domain
dotnet add Web reference Infrastructure

3.3 安装必要依赖

Web项目中安装关键NuGet包:

代码语言:bash
复制
# Bootstrap Blazor组件库
dotnet add package BootstrapBlazor --version 9.7.0

# EF Core 9.0 SQL Server提供器
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 9.0.0

# 身份认证
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore --version 9.0.0

# Excel处理
dotnet add package MiniExcel --version 1.41.2

四、核心代码实现

4.1 领域模型设计

Student.cs(领域层):

代码语言:csharp
复制
using System.ComponentModel.DataAnnotations;

namespace Domain.Entities;

public class Student
{
    public int StudentId { get; set; }
    
    [Required(ErrorMessage = "姓名不能为空")]
    [MaxLength(50)]
    public string Name { get; set; } = string.Empty;
    
    [Required]
    [RegularExpression(@"^\d{10}$", ErrorMessage = "学号必须为10位数字")]
    public string StudentNumber { get; set; } = string.Empty;
    
    [MaxLength(20)]
    public string Class { get; set; } = string.Empty;
    
    [EmailAddress]
    public string? Email { get; set; }
    
    public ICollection<Grade> Grades { get; set; } = new List<Grade>();
    public ICollection<StudentCourse> StudentCourses { get; set; } = new List<StudentCourse>();
}

Course.cs(领域层):

代码语言:csharp
复制
using System.ComponentModel.DataAnnotations;

namespace Domain.Entities;

public class Course
{
    public int CourseId { get; set; }
    
    [Required]
    [MaxLength(100)]
    public string CourseName { get; set; } = string.Empty;
    
    [Required]
    [MaxLength(20)]
    public string CourseCode { get; set; } = string.Empty;
    
    public int Credits { get; set; }
    
    public ICollection<Grade> Grades { get; set; } = new List<Grade>();
    public ICollection<StudentCourse> StudentCourses { get; set; } = new List<StudentCourse>();
}

Grade.cs(领域层):

代码语言:csharp
复制
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Domain.Entities;

public class Grade
{
    public int GradeId { get; set; }
    
    [ForeignKey("Student")]
    public int StudentId { get; set; }
    
    [ForeignKey("Course")]
    public int CourseId { get; set; }
    
    [Range(0, 100, ErrorMessage = "成绩必须在0-100之间")]
    public decimal Score { get; set; }
    
    [MaxLength(500)]
    public string? Remark { get; set; }
    
    public DateTime CreatedAt { get; set; } = DateTime.Now;
    
    // 导航属性
    public Student Student { get; set; } = null!;
    public Course Course { get; set; } = null!;
}

4.2 数据访问层实现

AppDbContext.cs(基础设施层):

代码语言:csharp
复制
using Domain.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace Infrastructure.Data;

public class AppDbContext : IdentityDbContext<IdentityUser>
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<Student> Students => Set<Student>();
    public DbSet<Course> Courses => Set<Course>();
    public DbSet<Grade> Grades => Set<Grade>();
    public DbSet<StudentCourse> StudentCourses => Set<StudentCourse>();

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        
        // 配置多对多关系
        builder.Entity<StudentCourse>()
            .HasKey(sc => new { sc.StudentId, sc.CourseId });
            
        // 设置索引
        builder.Entity<Student>()
            .HasIndex(s => s.StudentNumber)
            .IsUnique();
            
        builder.Entity<Course>()
            .HasIndex(c => c.CourseCode)
            .IsUnique();
            
        // 种子数据
        builder.Entity<Course>().HasData(
            new Course { CourseId = 1, CourseName = "高等数学", CourseCode = "MATH101", Credits = 4 },
            new Course { CourseId = 2, CourseName = "大学物理", CourseCode = "PHYS102", Credits = 3 },
            new Course { CourseId = 3, CourseName = "计算机导论", CourseCode = "CS103", Credits = 4 }
        );
    }
}

4.3 业务服务实现

StudentService.cs(应用层):

代码语言:csharp
复制
using Domain.Entities;
using Domain.Repositories;
using Infrastructure.Data;
using Microsoft.EntityFrameworkCore;

namespace Application.Services;

public class StudentService : IStudentService
{
    private readonly AppDbContext _context;
    
    public StudentService(AppDbContext context)
    {
        _context = context;
    }
    
    public async Task<List<Student>> GetAllStudentsAsync()
    {
        return await _context.Students
            .Include(s => s.Grades)
            .ThenInclude(g => g.Course)
            .ToListAsync();
    }
    
    public async Task<Student?> GetStudentByIdAsync(int id)
    {
        return await _context.Students
            .Include(s => s.Grades)
            .ThenInclude(g => g.Course)
            .FirstOrDefaultAsync(s => s.StudentId == id);
    }
    
    public async Task AddStudentAsync(Student student)
    {
        _context.Students.Add(student);
        await _context.SaveChangesAsync();
    }
    
    public async Task UpdateStudentAsync(Student student)
    {
        _context.Entry(student).State = EntityState.Modified;
        await _context.SaveChangesAsync();
    }
    
    public async Task DeleteStudentAsync(int id)
    {
        var student = await _context.Students.FindAsync(id);
        if (student != null)
        {
            _context.Students.Remove(student);
            await _context.SaveChangesAsync();
        }
    }
    
    // 成绩统计方法
    public async Task<GradeStatistics> GetGradeStatisticsAsync(int courseId)
    {
        var grades = await _context.Grades
            .Where(g => g.CourseId == courseId)
            .Select(g => g.Score)
            .ToListAsync();
            
        return new GradeStatistics
        {
            Average = grades.Any() ? grades.Average() : 0,
            Highest = grades.Any() ? grades.Max() : 0,
            Lowest = grades.Any() ? grades.Min() : 0,
            Count = grades.Count,
            PassRate = grades.Any() ? 
                (decimal)grades.Count(g => g >= 60) / grades.Count * 100 : 0
        };
    }
}

4.4 Blazor页面实现

学生列表页面(Pages/Students.razor):

代码语言:razor
复制
@page "/students"
@inject IStudentService StudentService
@inject NavigationManager NavManager
@inject ILogger<Students> Logger
@inject ToastService ToastService

<PageTitle>学生管理</PageTitle>

<Card Title="学生信息管理" Description="查看和管理所有学生信息">
    <Table TItem="Student" 
           Items="@students" 
           ShowToolbar="true"
           IsStriped="true"
           IsBordered="true"
           OnSaveAsync="OnSaveAsync"
           OnDeleteAsync="OnDeleteAsync"
           AutoGenerateColumns="true">
        
        <TableColumns>
            <TableColumn @bind-Field="@context.StudentId" IsVisible="false" />
            <TableColumn @bind-Field="@context.Name" />
            <TableColumn @bind-Field="@context.StudentNumber" />
            <TableColumn @bind-Field="@context.Class" />
            <TableColumn @bind-Field="@context.Email" />
            <TableColumn Title="操作">
                <Button Icon="fa-solid fa-edit" 
                        Size="ButtonSize.ExtraSmall"
                        OnClick="() => EditStudent(context.StudentId)">
                </Button>
                <Button Icon="fa-solid fa-graduation-cap" 
                        Size="ButtonSize.ExtraSmall"
                        OnClick="() => ViewGrades(context.StudentId)">
                </Button>
            </TableColumn>
        </TableColumns>
    </Table>
</Card>

@code {
    private List<Student> students = new();
    
    protected override async Task OnInitializedAsync()
    {
        await LoadStudents();
    }
    
    private async Task LoadStudents()
    {
        try
        {
            students = await StudentService.GetAllStudentsAsync();
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "加载学生数据失败");
            await ToastService.ShowError("加载数据失败", "错误");
        }
    }
    
    private async Task<bool> OnSaveAsync(Student student)
    {
        try
        {
            if (student.StudentId == 0)
            {
                await StudentService.AddStudentAsync(student);
                await ToastService.ShowSuccess("添加成功", "提示");
            }
            else
            {
                await StudentService.UpdateStudentAsync(student);
                await ToastService.ShowSuccess("更新成功", "提示");
            }
            await LoadStudents();
            return true;
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "保存学生数据失败");
            await ToastService.ShowError($"保存失败: {ex.Message}", "错误");
            return false;
        }
    }
    
    private async Task<bool> OnDeleteAsync(IEnumerable<Student> students)
    {
        try
        {
            foreach (var student in students)
            {
                await StudentService.DeleteStudentAsync(student.StudentId);
            }
            await LoadStudents();
            await ToastService.ShowSuccess("删除成功", "提示");
            return true;
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "删除学生数据失败");
            await ToastService.ShowError($"删除失败: {ex.Message}", "错误");
            return false;
        }
    }
    
    private void EditStudent(int id)
    {
        NavManager.NavigateTo($"/students/edit/{id}");
    }
    
    private void ViewGrades(int id)
    {
        NavManager.NavigateTo($"/students/{id}/grades");
    }
}

4.5 成绩统计图表实现

成绩分析页面(Pages/GradeAnalysis.razor):

代码语言:razor
复制
@page "/grade-analysis"
@inject IGradeService GradeService
@inject ICourseService CourseService
@inject ILogger<GradeAnalysis> Logger
@using Blazor.ECharts.Options.Series
@using Blazor.ECharts.Options.XAxis
@using Blazor.ECharts.Options.YAxis

<PageTitle>成绩分析</PageTitle>

<Card Title="成绩统计分析" Description="分析各课程成绩分布情况">
    <div class="row">
        <div class="col-md-3">
            <Select @bind-Value="selectedCourseId" 
                    Placeholder="选择课程" 
                    OnSelectedItemChanged="OnCourseChanged">
                @foreach (var course in courses)
                {
                    <SelectItem Value="@course.CourseId">@course.CourseName</SelectItem>
                }
            </Select>
        </div>
    </div>
    
    @if (statistics != null)
    {
        <div class="row mt-4">
            <div class="col-md-6">
                <Card Title="成绩分布">
                    <ECharts @ref="_chart" 
                             Options="_chartOptions" 
                             Style="height: 400px;"></ECharts>
                </Card>
            </div>
            <div class="col-md-6">
                <Card Title="统计指标">
                    <ul class="list-group">
                        <li class="list-group-item">
                            <strong>平均分:</strong> @statistics.Average.ToString("F1")
                        </li>
                        <li class="list-group-item">
                            <strong>最高分:</strong> @statistics.Highest
                        </li>
                        <li class="list-group-item">
                            <strong>最低分:</strong> @statistics.Lowest
                        </li>
                        <li class="list-group-item">
                            <strong>及格率:</strong> @statistics.PassRate.ToString("F1")%
                        </li>
                        <li class="list-group-item">
                            <strong>参考人数:</strong> @statistics.Count
                        </li>
                    </ul>
                </Card>
            </div>
        </div>
    }
</Card>

@code {
    private List<Course> courses = new();
    private int selectedCourseId = 0;
    private GradeStatistics? statistics;
    private ECharts? _chart;
    private EChartsOptions _chartOptions = new();
    
    protected override async Task OnInitializedAsync()
    {
        courses = await CourseService.GetAllCoursesAsync();
        if (courses.Any())
        {
            selectedCourseId = courses.First().CourseId;
            await OnCourseChanged(selectedCourseId);
        }
    }
    
    private async Task OnCourseChanged(int courseId)
    {
        if (courseId == 0) return;
        
        try
        {
            statistics = await GradeService.GetGradeStatisticsAsync(courseId);
            var distribution = await GradeService.GetGradeDistributionAsync(courseId);
            
            // 配置图表
            _chartOptions = new EChartsOptions
            {
                Title = new Title { Text = "成绩分布直方图" },
                Tooltip = new Tooltip { Trigger = "axis", AxisPointer = new AxisPointer { Type = "shadow" } },
                XAxis = new XAxis
                {
                    Type = AxisType.Category,
                    Data = new List<string> { "0-59", "60-69", "70-79", "80-89", "90-100" }
                },
                YAxis = new YAxis { Type = AxisType.Value },
                Series = new List<ISeries>
                {
                    new BarSeries
                    {
                        Name = "学生人数",
                        Data = new List<double>
                        {
                            distribution.Fail,
                            distribution.Pass,
                            distribution.Good,
                            distribution.Excellent,
                            distribution.Expert
                        },
                        ItemStyle = new ItemStyle
                        {
                            Color = new JsFunction("function(params) { return params.dataIndex === 0 ? '#ff4d4f' : '#52c41a'; }")
                        }
                    }
                }
            };
            
            StateHasChanged();
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "加载成绩统计失败");
        }
    }
}

4.6 身份认证与授权

Program.cs配置:

代码语言:csharp
复制
var builder = WebApplication.CreateBuilder(args);

// 添加数据库上下文
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
    
// 添加身份认证
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<AppDbContext>();
    
// 添加授权策略
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("TeacherOnly", policy => policy.RequireRole("Teacher"));
    options.AddPolicy("StudentOnly", policy => policy.RequireRole("Student"));
});

// 添加服务
builder.Services.AddScoped<IStudentService, StudentService>();
builder.Services.AddScoped<ICourseService, CourseService>();
builder.Services.AddScoped<IGradeService, GradeService>();

// 添加Blazor组件
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();
    
// 添加Bootstrap Blazor组件
builder.Services.AddBootstrapBlazor();

// 添加ECharts
builder.Services.AddECharts();

var app = builder.Build();

// 配置中间件
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

// 初始化角色和管理员用户
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    try
    {
        await SeedData.Initialize(services);
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "An error occurred seeding the DB.");
    }
}

app.Run();

五、性能优化策略

5.1 服务器GC优化

.NET 9引入的动态适应应用大小(DATAS) 垃圾回收机制可显著减少内存占用:

代码语言:csharp
复制
// Program.cs中配置
builder.Services.Configure<GCSettings>(settings =>
{
    settings.LatencyMode = GCLatencyMode.SustainedLowLatency;
});

5.2 组件渲染优化

使用ShouldRender方法减少不必要的渲染:

代码语言:csharp
复制
protected override bool ShouldRender()
{
    // 仅当数据实际更改时才重新渲染
    return _dataHasChanged;
}

5.3 数据加载优化

实现虚拟滚动加载大量数据:

代码语言:razor
复制
<Virtualize Items="@students" Context="student" ItemsProvider="LoadStudents">
    <div class="student-item">
        @student.Name - @student.StudentNumber
    </div>
    
    <LoadingTemplate>
        <div class="text-center py-4">加载中...</div>
    </LoadingTemplate>
</Virtualize>

@code {
    private async ValueTask<ItemsProviderResult<Student>> LoadStudents(ItemsProviderRequest request)
    {
        var result = await StudentService.GetStudentsAsync(
            request.StartIndex, request.Count);
            
        return new ItemsProviderResult<Student>(
            result.Items, result.TotalCount);
    }
}

六、部署指南

6.1 Windows环境部署(IIS)

  1. 发布应用:dotnet publish -c Release -o ./publish
  2. 配置IIS
    • 安装.NET 9 Hosting Bundle
    • 创建应用池(无托管代码)
    • 设置物理路径指向publish文件夹
  3. 配置web.config:<?xml version="1.0" encoding="utf-8"?> <configuration> <location path="." inheritInChildApplications="false"> <system.webServer> <handlers> <add name="aspNetCore" path="\*" verb="\*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath=".\StudentGradeManagement.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" /> </system.webServer> </location> </configuration>

6.2 Linux环境部署(Nginx)

  1. 安装依赖:sudo apt-get update sudo apt-get install -y aspnetcore-runtime-9.0 nginx# /etc/systemd/system/student-grade.service [Unit] Description=Student Grade Management System After=network.target [Service] WorkingDirectory=/var/www/student-grade ExecStart=/usr/bin/dotnet StudentGradeManagement.dll Restart=always RestartSec=10 User=www-data Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install] WantedBy=multi-user.target
  2. 创建系统服务
  3. 配置Nginx:server { listen 80; server_name your-domain.com; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }

七、总结与扩展

7.1 项目回顾

本文构建的学生成绩管理系统实现了以下核心价值:

  • 技术先进性:基于.NET 9和Blazor Server,采用分层架构设计
  • 功能完整性:覆盖学生管理、课程管理、成绩管理全流程
  • 性能优化:通过DATAS GC、组件渲染控制提升系统响应速度
  • 安全可靠:基于ASP.NET Core Identity的身份认证与授权

7.2 功能扩展建议

  1. 移动应用:使用Blazor Hybrid开发跨平台移动应用
  2. 高级报表:集成RDLCSyncfusion ReportViewer生成复杂报表
  3. AI分析:添加机器学习模型预测学生成绩趋势
  4. 通知系统:集成SignalR实现成绩更新实时推送

7.3 学习资源

通过本文的指导,您已掌握使用Blazor和.NET 9构建企业级Web应用的核心技能。这个成绩管理系统不仅满足了教学管理的基本需求,更为您提供了一个可扩展的架构基础,助力您在.NET生态系统中进一步探索和创新。

附录:完整项目结构

代码语言:txt
复制
StudentGradeManagement/
├── Application/
│   ├── Dtos/
│   ├── Interfaces/
│   └── Services/
├── Domain/
│   ├── Entities/
│   └── Interfaces/
├── Infrastructure/
│   ├── Data/
│   └── Migrations/
├── Web/
│   ├── Components/
│   ├── Pages/
│   ├── Properties/
│   ├── Services/
│   ├── Shared/
│   ├── wwwroot/
│   ├── App.razor
│   ├── Program.cs
│   └── ...
├── StudentGradeManagement.sln
└── README.md

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、需求分析
    • 1.1 用户角色与功能需求
    • 1.2 功能模块划分
    • 1.3 非功能需求
  • 二、架构设计
    • 2.1 技术栈选型
    • 2.2 分层架构设计
    • 2.3 数据库设计
  • 三、环境搭建
    • 3.1 开发环境准备
    • 3.2 项目结构调整
    • 3.3 安装必要依赖
  • 四、核心代码实现
    • 4.1 领域模型设计
    • 4.2 数据访问层实现
    • 4.3 业务服务实现
    • 4.4 Blazor页面实现
    • 4.5 成绩统计图表实现
    • 4.6 身份认证与授权
  • 五、性能优化策略
    • 5.1 服务器GC优化
    • 5.2 组件渲染优化
    • 5.3 数据加载优化
  • 六、部署指南
    • 6.1 Windows环境部署(IIS)
    • 6.2 Linux环境部署(Nginx)
  • 七、总结与扩展
    • 7.1 项目回顾
    • 7.2 功能扩展建议
    • 7.3 学习资源
  • 附录:完整项目结构
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档