【问题标题】:Testing Entity Framework Core Migrations测试实体框架核心迁移
【发布时间】:2022-02-26 08:02:08
【问题描述】:
您如何使用单元/集成测试来确保代码优先迁移在填充的先前版本数据库上正常工作,包括将数据从一个列或表映射到另一个的任何附加代码?
我发现了一些先前的答案,它们使用了 System.Data.Entity 命名空间中的类,但似乎这些在 Entity Framework Core 中已经过时,并且无法手动控制迁移?
我为自己找到了一个解决方案,我将发布,但我欢迎其他更好的解决方案。
【问题讨论】:
标签:
c#
unit-testing
entity-framework-core
mstest
【解决方案1】:
数据库由 Context 类、ContextModelSnapshot 类、一系列迁移文件以及数据表存储的 C# 对象定义。
如果您尚未创建迁移,请将所有这些文件复制到您的测试项目中,并使用后缀重命名所有类,例如“我的数据实体”=>“我的数据实体版本 1”。相应地编辑捆绑的 .Design.cs 文件。然后,在原始文件上创建新的迁移。
如果您已创建新迁移但无法后退,您可以手动编辑 ContextModelSnapshot 文件以恢复更改。
这项工作的关键是两者都指向同一个数据库文件。一种期待原始状态,另一种期待升级后的状态。
在您的测试用例中,您可以这样做:
[TestInitialize]
public void TestInit()
{
using (var db = new MyDataContext())
db.Database.EnsureDeleted(); // reset database before each test
}
[TestMethod]
public void Migrate_Version1_To_Version2_On_Populated_Database()
{
using (var db = new MyDataContextVersion1())
db.Database.Migrate(); // create database and apply migrations up through Version 1
// populate the Version 1 database
App.InitializeDatabase(); // whatever method you would normally call to read/update the database
// assert statements to test that the Version 2 database looks like you expect.
}
InitializeDatabase() 看起来像这样:
public void InitializeDatabase()
{
using (var db = new MyDataContext())
{
db.Database.Migrate();
// detect if upgrade needed and set new columns
db.SaveChanges();
}
}
请注意,此解决方案的部分动机是使用 SQLite,它不支持在迁移中删除列。它阻止了我尝试在迁移中做任何更花哨的事情。