EF Core 2.1内存数据库无法更新记录,求助排查
嘿,我之前也踩过In Memory数据库的这个坑!你遇到的问题大概率不是EF的Bug,而是DbContext实例的生命周期和获取方式导致的——毕竟In Memory数据库虽然共享数据,但每个DbContext都有自己独立的实体跟踪缓存,一旦实例不匹配,就会出现“更新了但查不到”的情况。
先看你的TestFixture代码,问题出在获取DbContext的方式上:
public IDatabaseService DbContext { get { return _testServer.Host.Services.GetService<DatabaseService>(); } }
这里直接从根服务容器获取DatabaseService(也就是你的DbContext),但如果在Startup里你是用默认的AddDbContext注册的,它的生命周期是Scoped。根服务容器获取Scoped服务时,会创建一个单例实例,而API请求中每个请求都会生成一个新的Scoped DbContext实例——这就导致:API里的上下文更新了数据并保存到In Memory库,但Fixture里的旧上下文还拿着自己的跟踪缓存,自然查不到更新后的记录。
解决步骤
修改Fixture中获取DbContext的方式
不要直接从根服务容器拿,而是创建一个服务范围来获取Scoped实例。可以给Fixture加一个方法:public IDatabaseService GetScopedDbContext() { var scope = _testServer.Host.Services.CreateScope(); return scope.ServiceProvider.GetRequiredService<DatabaseService>(); }或者在测试中直接使用
using块创建范围,确保每次查询都用新的上下文实例。调整测试逻辑,用新上下文查询更新结果
执行API更新请求后,一定要用新的Scoped上下文去查询数据,比如:[Fact] public async Task Update_Record_Should_Succeed() { // 1. 初始化测试数据 using (var dbContext = _fixture.GetScopedDbContext()) { dbContext.YourEntities.Add(new YourEntity { Id = 1, Value = "Old Value" }); await dbContext.SaveChangesAsync(); } // 2. 发送更新请求 var updateContent = new StringContent(JsonConvert.SerializeObject(new { Value = "New Value" }), Encoding.UTF8, "application/json"); var response = await _fixture.TestClient.PutAsync("/api/yourentities/1", updateContent); response.EnsureSuccessStatusCode(); // 确保请求无异常 // 3. 用新上下文查询验证结果 using (var dbContext = _fixture.GetScopedDbContext()) { var updatedEntity = await dbContext.YourEntities.FindAsync(1); Assert.Equal("New Value", updatedEntity.Value); } }额外检查点
- 确认你的API代码中确实调用了
SaveChanges()或SaveChangesAsync(),并且没有被异常中断(可以通过API响应状态码判断)。 - 如果你的实体有并发令牌(比如
[Timestamp]属性),In Memory数据库对并发的处理和SQL Server略有不同,但你说SQL库正常,这个大概率不是问题。
- 确认你的API代码中确实调用了
这个调整后,你应该就能看到In Memory数据库里的更新记录了——本质就是让测试用的上下文和API用的上下文处于相同的Scoped生命周期,保证数据跟踪的一致性。
内容的提问来源于stack exchange,提问作者Chris Sainty

