You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core中AddSingleton失效:单例服务重复添加初始数据

问题分析与解决方案

问题根源

  1. 控制器注入类型不匹配:你注册的是ICourseService的单例,但控制器直接注入具体类型CourseService,DI容器会为CourseService创建新实例(未注册其单例),导致每次请求都执行构造函数,重复添加数据。
  2. 未做数据存在性检查:构造函数中直接添加数据,即使服务是单例,也会在应用重启时重复添加;而当前每次刷新都添加的核心原因是服务实例未被复用。
  3. 单例依赖Scoped服务的风险:CourseService是单例,但依赖的DataContext默认是Scoped生命周期,会导致上下文被长期持有,引发连接泄漏、状态混乱等潜在问题。

解决方案

1. 修正控制器注入方式

控制器改为注入接口ICourseService,确保使用注册的单例实例:

public class CourseController : Controller
{
    private readonly ICourseService _courseService;

    public CourseController(ICourseService courseService)
    {
        _courseService = courseService;
    }

    [Route("courses")]
    public async Task<IActionResult> GetCourses()
    {
        var courses = await _courseService.GetCoursesAsync();
        return View("CourseList", courses);
    }
}

2. 添加数据前检查存在性

在服务构造函数中先查询数据库,仅当数据不存在时再添加:

public class CourseService : BaseService<Course, CourseDto>, ICourseService
{
    public CourseService(IMapper mapper, DataContext context) : base(mapper,context)
    {
        // 替换为你的课程唯一标识字段(如名称、ID等)
        if (!context.Courses.Any(c => c.Name == "初始课程1"))
        {
            context.Courses.Add(new Course { Name = "初始课程1", ... });
        }
        if (!context.Courses.Any(c => c.Name == "初始课程2"))
        {
            context.Courses.Add(new Course { Name = "初始课程2", ... });
        }
        context.SaveChanges();
    }

    public IEnumerable<CourseDto> GetCourses() { ... }

    public async Task<IEnumerable<CourseDto>> GetCoursesAsync() { ... }
}

3. 优化初始化逻辑(推荐)

将初始数据添加逻辑移到应用启动阶段,避免单例服务持有Scoped上下文:

// 在Program.cs中,构建主机后执行初始化
var host = builder.Build();

using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var context = services.GetRequiredService<DataContext>();
    
    // 检查并添加初始数据
    if (!context.Courses.Any(c => c.Name == "初始课程1"))
    {
        context.Courses.Add(new Course { Name = "初始课程1", ... });
    }
    if (!context.Courses.Any(c => c.Name == "初始课程2"))
    {
        context.Courses.Add(new Course { Name = "初始课程2", ... });
    }
    context.SaveChanges();
}

host.Run();

4. 确认服务注册正确性

确保ICourseService和DataContext的注册配置正确:

services.AddSingleton<ICourseService, CourseService>();
services.AddDbContext<DataContext>(options => 
    options.UseSqlite("你的SQLite连接字符串"));

内容的提问来源于stack exchange,提问作者Nika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:05:19