MsTest中SQLite内存数据库无法清空的解决办法
问题描述
我有一个MsTest项目,代码如下:
private MyDbContext _dbCtx; private MyDbContext CreateSqlLiteDbCtx() { var dbConnection = new SqliteConnection() { ConnectionString = "Data Source=:memory:", }; dbConnection.Open(); var _contextOptions = new DbContextOptionsBuilder<MyDbContext>() .UseSqlite(dbConnection) .Options; return new MyDbContext(_contextOptions); } [TestInitialize] public void InitTests() { _dbCtx= CreateSqlLiteDbCtx(); } [TestCleanup] public void CleanUp() { _dbCtx?.Database.EnsureDeleted(); // Remove from memory _dbCtx?.Dispose(); } [TestMethod] public async Task MyTest() { if (_dbCtx.Database.EnsureCreated()) { // run test } catch (Exception) { throw; } }
内存数据库中已存在无效数据,我希望清空数据库以获得全新的测试环境,但使用EnsureDeleted重新运行单元测试后并未生效,请问该如何彻底清空这个数据库?
解决方案
1. 先搞懂内存SQLite的核心特性
内存SQLite数据库的生命周期完全绑定在打开的连接上,只要连接没关闭,数据库就会一直存在于内存中。你当前的清理逻辑只Dispose了上下文,但底层的SQLite连接可能没被正确关闭释放,导致旧数据库残留。
2. 修正清理逻辑,彻底销毁连接
修改CleanUp方法,手动关闭并释放底层的SQLite连接:
[TestCleanup] public void CleanUp() { if (_dbCtx != null) { // 获取上下文绑定的SQLite连接 var dbConnection = _dbCtx.Database.GetDbConnection(); // 确保连接关闭 if (dbConnection.State == System.Data.ConnectionState.Open) { dbConnection.Close(); } // 释放上下文并置空 _dbCtx.Dispose(); _dbCtx = null; } }
这样每次测试结束后,连接被关闭,内存数据库会被自动销毁,下一次测试初始化时会创建全新的空库。
3. 不要依赖EnsureCreated的返回值控制测试逻辑
内存数据库每次通过新连接创建时都是完全空的,EnsureCreated一定会返回true。如果之前的连接没释放,旧数据库没销毁,EnsureCreated会返回false,导致你的测试逻辑跳过执行,这也是数据残留的原因之一。建议直接执行测试逻辑,不需要判断EnsureCreated的结果:
[TestMethod] public async Task MyTest() { // 直接执行测试逻辑,无需判断EnsureCreated // run test }
4. 备选方案:不清空数据库,直接重置数据
如果不想销毁连接,也可以在测试后手动清空所有表的数据并重置自增序列:
private async Task ResetDatabase() { // 先禁用外键约束,避免清空表时出错 await _dbCtx.Database.ExecuteSqlRawAsync("PRAGMA foreign_keys = OFF;"); // 获取所有实体对应的表名 var tableNames = _dbCtx.Model.GetEntityTypes() .Select(t => t.GetTableName()) .Where(name => !string.IsNullOrEmpty(name)) .Distinct(); foreach (var table in tableNames) { // 清空表数据 await _dbCtx.Database.ExecuteSqlRawAsync($"DELETE FROM {table};"); // 重置自增序列(如果有的话) await _dbCtx.Database.ExecuteSqlRawAsync($"DELETE FROM sqlite_sequence WHERE name='{table}';"); } // 恢复外键约束 await _dbCtx.Database.ExecuteSqlRawAsync("PRAGMA foreign_keys = ON;"); await _dbCtx.SaveChangesAsync(); }
在CleanUp中调用await ResetDatabase();即可实现数据重置。
内容的提问来源于stack exchange,提问作者SlappingTheBass12
相关产品推荐
相关产品推荐

