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

微服务中ApplicationDbContext重复创建致内存数据库种子数据丢失问题

问题描述

我正在开发一个微服务项目:

  • 项目1:CustomerService(提供客户编辑API)
  • 项目2:CoreService(为.NET Core微服务提供基础配置,包含供项目1使用的ApplicationDbContext,以及ICustomerRepository及其实现CustomerRepostory等仓储)

注:使用内存数据库。

现有代码

CustomerService(项目1)的Program.cs

var builder = WebApplication.CreateBuilder(args);

var serviceProvider = builder.Services.AddDbContext<ApplicationDbContext>().BuildServiceProvider();

using (var context = serviceProvider.GetRequiredService<ApplicationDbContext>())
{
    context.SeedData();
}

builder.Services.AddHttpContextAccessor();
builder.Services.AddHttpClient();
builder.Services.AddScoped<IBaseService, BaseService>();

CoreService(项目2)的Program.cs

//add database related services
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseInMemoryDatabase("InMemoryDB");
});

CoreService中的ApplicationDbContext

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options) 
    {
    }

    public DbSet<Customer> Customers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseInMemoryDatabase("InMemoryDB");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Customer>().HasKey(b => b.Id); // declaring Id as Primary key
    }

    public void SeedData()
    {
        // Ensure the database is created
        this.Database.EnsureCreated();

        if (!this.Customers.Any())
        {
            // Add initial data if the Bookings table is empty
            this.Customers.AddRange(
               new Customer
               {
                   Name = "Srijani",
                   Email = "abc@gmail.com",
                   Address = "Abcstraße 4, 123Hamburg",
                   ContactNumber = "9876541232"
               }
            );

            // Save changes after seeding data
            this.SaveChanges();
        }
    }
}

问题:运行项目时,调用CustomerService的API无法看到初始化的种子数据,推测是调用API时重新创建了ApplicationDbContext实例。如何避免这种情况,确保种子数据能被API访问到?


解决方案

核心问题是种子数据所在的内存数据库实例和API使用的不是同一个,加上DbContext注册与初始化方式有误,按以下步骤修复:

1. 清理ApplicationDbContext的冗余配置

移除OnConfiguring方法中的硬编码配置,因为已经在Program.cs中通过DbContextOptions注入了配置,重复配置会导致创建独立的数据库实例:

// 删除这段代码
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseInMemoryDatabase("InMemoryDB");
}

2. 修正CustomerService中DbContext的注册与种子初始化逻辑

不要提前构建ServiceProvider执行种子操作,而是在应用启动完成后,从容器获取DbContext实例执行初始化,确保使用的是和API一致的注册实例:

修改CustomerService的Program.cs:

var builder = WebApplication.CreateBuilder(args);

// 先注册DbContext,确保配置与CoreService一致
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseInMemoryDatabase("InMemoryDB");
});

builder.Services.AddHttpContextAccessor();
builder.Services.AddHttpClient();
builder.Services.AddScoped<IBaseService, BaseService>();

var app = builder.Build();

// 应用启动后,通过作用域获取DbContext执行种子初始化
using (var scope = app.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    context.SeedData();
}

// 后续中间件配置
app.MapControllers();
app.Run();

3. 确保内存数据库名称完全一致

内存数据库通过名称标识实例,所有配置中必须使用完全相同的名称(如"InMemoryDB"),不能有拼写错误或大小写差异,否则会创建独立的数据库。

4. 保持DbContext的默认生命周期

AddDbContext默认注册为Scoped生命周期(每个请求一个实例),这是合理的。API请求时会创建新的DbContext实例,但会连接到同一个内存数据库,因此能读取到种子数据,无需修改为Singleton或Transient。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 21:56:03