在这里阅读了许多问题后,在 Asp.Net 的 Github 上(我想到了这个 https://github.com/aspnet/EntityFrameworkCore/issues/5096,ServerFault 和 SoftwareEngineering,我决定问一个我自己的问题。
问题
代码优先迁移让早期开发过程变得异常轻松。登台或生产环境更难更新,尤其是在可能需要频繁更新的初始部署期间。
更新生产数据库要困难得多,而且由于许多很好的原因,自动迁移是不可能的——这些原因都在文档中写得很好,解释得很好,让我忽略了这条路线。
现在我正在寻找中间立场。
Approach
一旦应用程序的新版本发布,我们就可以检测是否有待处理的更改(诊断中间件“DatabaseErrorPageMiddleware”在我们使用它时已经执行此操作,显然我们不会在生产环境中执行此操作)。如果存在待处理的迁移,我们可以使站点脱机(有多种方法,为简洁起见,跳过),但仍然允许管理用户登录系统 - 可能是带有特定声明“IsAllowedToMigrate”:“true”的用户。
对于该用户,我们可以向他的管理导航添加一个操作。该页面可以列出待处理的更改,并公开更新到当前的方法(为了简单起见)。此操作方法甚至可以合并代码来备份数据库或类似的检查和平衡。
关于环境的假设
对于我的预期方法,我假设采用一种相当非正式的方法来更新应用程序 - 不涉及可能需要脚本的外部 DBA,迁移已经在生产数据库的最新备份等上进行了测试。
其次,我假设该网站可以显示为离线状态;我们打电话给ImaginarySiteManager.DisplayOffline(AVeryNiceMessage)
。该虚构站点仍然可以提供管理后端的登录。
我还针对 SQL Server 进行了定制,并且对其他提供商一无所知。
一些代码
大部分代码都无耻地从中间件的源代码中窃取,为了测试它,我刚刚使用了管理员可用的 ActionMethod,尚未附加任何输出或操作
public async Task<IActionResult> TestPendingMigrations([FromServices] SomeDbContext dbContext)
{
var relationalDatabaseCreator = dbContext.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator;
var migrationsAssembly = dbContext.GetService<IMigrationsAssembly>();
var modelDiffer = dbContext.GetService<IMigrationsModelDiffer>();
var databaseExists = await relationalDatabaseCreator.ExistsAsync();
// HasDifferences will return true if there is no model snapshot, but if there is an existing database
// and no model snapshot then we don't want to show the error page since they are most likely targeting
// and existing database and have just misconfigured their model
var pendingModelChanges
= (!databaseExists || migrationsAssembly.ModelSnapshot != null)
&& modelDiffer.HasDifferences(migrationsAssembly.ModelSnapshot?.Model, dbContext.Model);
var pendingMigrations
= (databaseExists
? await dbContext.Database.GetPendingMigrationsAsync()
: dbContext.Database.GetMigrations())
.ToArray();
// get Sitemanager.CurrentSite -> isClosed; closedMessage = "updates pending.." or similar.
// add action to admin menu (update database).
return new EmptyResult();
}
卡在这里
首先,测试挂起的迁移是否存在应该位于 Startup 中或紧邻 Startup 的位置。我正在尝试找出设置此功能的最佳位置。DbContext.OnModelCreating
看起来是一个不错的起点?
但我如何等待完成并插入我的福尔摩斯模块进行调查?
应用迁移的代码也写在摩西的第六本书中:https://github.com/aspnet/AspNetCore/blob/master/src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.cshtml https://github.com/aspnet/AspNetCore/blob/master/src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.cshtml
所以理论上应该可以
- 启动(更新或未更新)应用程序
- 启动(或派生)确定数据库是否与模型匹配(
pendingMigrations
)并使网站离线
- 具有特定权限(声明或其他)的管理员可以登录并直接从后端运行迁移 - 作为唯一授权人员在必须发生时执行此操作
这是一个可行的方法吗?我错过了吗Microsoft.EntityFramework.Extensions.ProductionMigrationMadeSimple
延伸并过度思考这个?