EF Core内存数据库(
InMemoryProvider)不是用来跑生产环境的,它是专为快速、隔离的单元测试设计的轻量级模拟工具。用它,你不用装SQL Server、不用连网络、不依赖Docker容器,几毫秒就能启动一个干净的“假数据库”。
安装与基础配置
先装NuGet包:
dotnet add package Microsoft.EntityFrameworkCore.InMemory或在Visual Studio中通过NuGet包管理器搜索安装
然后在测试代码里配置DbContext选项:
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(databaseName: "TestDb_" + Guid.NewGuid()) // 推荐用唯一名
.Options;
每次用不同
databaseName,就得到一个完全独立的内存数据库实例——避免测试间数据污染。
写测试时的关键操作
内存数据库不自动建表,也不执行迁移,所以你得靠代码“手动初始化”数据:
直接调context.AddRange()+
context.SaveChanges()插入测试数据 或者封装一个
SeedData(context)方法,在每个测试前调用 不需要
EnsureCreated(),它对InMemory无效;也不要调
Migrate(),它不支持迁移
示例:
using var context = new AppDbContext(options);
context.Users.AddRange(
new User { Id = 1, Name = "Alice" },
new User { Id = 2, Name = "Bob" });
context.SaveChanges();
var found = context.Users.FirstOrDefault(u => u.Name == "Alice");
Assert.NotNull(found);
注意它的行为边界
它快,但不等于“真实数据库”。以下情况容易踩坑:
不支持JOIN、GROUP BY、子查询等复杂SQL语义——查询会被转成LINQ to Objects执行,结果可能和SQL Server不一致 DateTime默认值不会自动生成:比如public DateTime CreatedAt { get; set; }会变成0001-01-01,需手动赋值或配
HasValueGenerator<datetimevaluegenerator>()</datetimevaluegenerator>没有事务回滚能力:
SaveChanges()后数据就“真存了”,只能靠
context.Database.EnsureDeleted()清空整个库 不校验外键约束、唯一索引、数据库触发器等——这些逻辑在内存中被跳过
什么时候该换SQLite In-Memory?
如果你的测试需要验证:
SQL语法是否正确(如ORDER BY加
LIMIT) 事务行为(比如并发修改、回滚效果) 外键级联删除、唯一约束报错 集成测试阶段想更贴近生产环境
那就改用
Microsoft.EntityFrameworkCore.Sqlite配合
DataSource=:memory:——它更接近真实数据库,只是仍运行在进程内。
基本上就这些。用对场景,它就是单元测试的加速器;硬套在不该用的地方,反而掩盖真实问题。
