MVC中硬编码的Employee列表每次Web API请求重置仅返回初始三条数据如何解决
问题描述
我花费了数小时理解MVC中的硬编码Model List概念,以下是我的代码,其中List<employee> employees变量存在问题。
using sampleProject.Models; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace sampleProject.Services { public class SampleData : ISampleData { private List<Employee> employees = new List<Employee>() { new Employee() { id=1, Name="Shubham", Code=1001, Email="a@a.com" }, new Employee() { id=2, Name="Shubham2", Code=1002, Email = "a2@a.com" }, new Employee() { id=3, Name="Shubham3", Code=1003, Email="a3@a.com" } }; public Employee CreateEmployee(Employee employee) { employee.id = employees.Count() + 1; employees.Add(employee); return employee; } public String DeleteEmployee(int id) { employees.Remove(GetEmployee(id)); return "Employee record with id : " + id.ToString() + " deleted"; } public Employee EditEmployee(int id, Employee employee) { var existingEmployee = GetEmployee(id); existingEmployee.Name = employee.Name; existingEmployee.Code = employee.Code; existingEmployee.Email = employee.Email; return existingEmployee; } public Employee GetEmployee(int? Id) { return (employees.SingleOrDefault(x => x.id == Id)); } public List<Employee> GetEmployees() { return employees; } } }
我可以正常执行新增、更新、删除操作,但调用GetEmployees()时仅返回我硬编码的三条记录,每次Web API请求时硬编码数据都会自动重置,请问该如何解决?
解决方案
根本原因
你遇到的问题是ASP.NET Core服务生命周期和内存数据非持久化共同导致的:
默认情况下如果你的SampleData服务注册为Scoped(每次请求新建一个实例)或者Transient(每次注入新建一个实例),每次新请求进来都会重新执行SampleData类的字段初始化逻辑,硬编码的3条数据会重置,之前请求中对List的增删改都存在上一个实例的内存中,自然无法保留。
方案1:本地测试快速修复(注册为单例服务)
只需要修改服务注册代码,让整个应用生命周期内只创建一个SampleData实例,修改后的数据就会在多次请求之间保留:
// .NET 6+ 写在Program.cs的服务注册区域 builder.Services.AddSingleton<ISampleData, SampleData>();
注意事项
List<T>不是线程安全的,多并发请求修改时会抛出异常,建议给增删改操作加锁:
public class SampleData : ISampleData { // 新增锁对象 private readonly object _lock = new(); private List<Employee> employees = new List<Employee>() { // 原有硬编码数据不变 }; public Employee CreateEmployee(Employee employee) { lock(_lock) { employee.id = employees.Count + 1; employees.Add(employee); return employee; } } // Delete、Edit方法同理,所有修改employees的逻辑都套一层lock即可 }
- 该方案仅适合本地测试:应用重启(代码重新编译、服务器重启)后所有修改的数据都会丢失,回到初始的3条硬编码记录。
方案2:生产环境方案(持久化到数据库)
要永久保存数据必须存储到磁盘而非内存,正规做法是用EF Core对接数据库:
- 安装对应Nuget包:
Microsoft.EntityFrameworkCore、对应数据库的驱动包(比如SQL Server用Microsoft.EntityFrameworkCore.SqlServer,轻量测试用SQLite可以装Microsoft.EntityFrameworkCore.Sqlite) - 新增DbContext类:
public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Employee> Employees { get; set; } // 初始化种子数据,对应你原来的3条硬编码记录 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Employee>().HasData( new Employee { id=1, Name="Shubham", Code=1001, Email="a@a.com" }, new Employee { id=2, Name="Shubham2", Code=1002, Email="a2@a.com" }, new Employee { id=3, Name="Shubham3", Code=1003, Email="a3@a.com" } ); } }
- 改造
SampleData类,操作数据库而非内存List:
public class SampleData : ISampleData { private readonly AppDbContext _dbContext; public SampleData(AppDbContext dbContext) { _dbContext = dbContext; } public Employee CreateEmployee(Employee employee) { _dbContext.Employees.Add(employee); _dbContext.SaveChanges(); return employee; } public string DeleteEmployee(int id) { var emp = GetEmployee(id); if(emp != null) { _dbContext.Employees.Remove(emp); _dbContext.SaveChanges(); } return $"Employee record with id : {id} deleted"; } public Employee EditEmployee(int id, Employee employee) { var existingEmployee = GetEmployee(id); existingEmployee.Name = employee.Name; existingEmployee.Code = employee.Code; existingEmployee.Email = employee.Email; _dbContext.SaveChanges(); return existingEmployee; } public Employee GetEmployee(int? Id) { return _dbContext.Employees.SingleOrDefault(x => x.id == Id); } public List<Employee> GetEmployees() { return _dbContext.Employees.ToList(); } }
- 在Program.cs中注册服务:
// 注册DbContext builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")) ); // SampleData注册为Scoped即可 builder.Services.AddScoped<ISampleData, SampleData>();
- 在appsettings.json中配置数据库连接字符串,执行EF Core迁移更新数据库后即可使用,数据会永久保存在数据库中,不会因为请求或应用重启丢失。
内容的提问来源于stack exchange,提问作者shubham shaw
相关产品推荐
相关产品推荐

