If your ASP.NET Core project is connecting to your database via entity framework, you can't be unfamiliar with the script: dotnet ef database update
. Without executing the script your database is not the latest and this may cause some issues. Traditionally we update the database every time we start our app or publish our app. But we may forget this process and it costs us work. How can we automatically update our database with our application starts?
Before doing this, you need to know that migrating the database automatically is dangerous.
- Migrations may cause the database to lose data.
- You may work on an obsolete branch.
- Migrations may fail.
Migrations may cause your database to lose data. Like your migration may drop some table. Not all environments expect to do that. This may be safe in your development environment but very dangerous in the production environment. This is the main reason why some applications do not migrate automatically.
Now we usually code with git or other version control tools. Switching branches and collaborate with others is more simple. But typically our database doesn't switch branch with your code. If you switched to another branch and just run the application, the migrations may ruin your database and hard for you to recover.
Migrations may fail because of connection reasons or data conflict. If you migrate the database automatically, you will not be warned and this is dangerous because a bigger problem will occur while your service is online.
In one word: Applying migration is a dangerous action. Unless you can ensure everything is fine or you are not suggested to automatically update the database.
To enable it, you need to add the following dependencies to your project:
<PackageReference Include="Polly" Version="7.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
With the library Polly
you can retry a task easily.
And then, copy the following code to your project:
public static IHost MigrateDbContext<TContext>(
this IHost host)
where TContext : DbContext
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>();
var context = services.GetService<TContext>();
try
{
logger.LogInformation($"Migrating database associated with context {typeof(TContext).Name}");
var retry = Policy.Handle<Exception>().WaitAndRetry(new[]
{
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(15),
});
retry.Execute(() =>
{
context.Database.Migrate();
});
logger.LogInformation($"Migrated database associated with context {typeof(TContext).Name}");
}
catch (Exception ex)
{
logger.LogError(ex, $"An error occurred while migrating the database used on context {typeof(TContext).Name}");
}
}
return host;
}
It creates an extended method for IHost which allows you to upgrade your database automatically after the application starts. It uses your application's default service provider to create a scope and get your DBContext
. And try to migrate the database to the latest status.
If your database is empty or does not exists at all, the script can also create your database automatically.
Finally, use the extend method in your startup process. Like this:
public static void Main(string[] args)
{
CreateHostBuilder(args)
.Build()
.MigrateDbContext<YourDbContext>()
.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}
Try to start your application, and monitor if it can successfully execute the update process.
When you are executing other ef
commands like dotnet ef migrations add Test
and the script will not be executed. Your database is still the same.
这篇文章提供了一个关于在ASP.NET Core应用启动时自动更新数据库的有用解决方案。让我详细总结一下本文的内容,并提出一些建设性的反馈。
核心理念
作者探讨了在ASP.NET Core项目中使用Entity Framework进行数据库迁移的问题,强调了手动执行
dotnet ef database update
脚本可能带来的风险和不便。文章的核心观点是:虽然自动数据库迁移可以简化开发流程,但需要谨慎处理以避免潜在的风险。主要优点:
清晰的危险警示
作者明确指出了自动迁移的三大风险:数据丢失、分支问题和迁移失败。这种透明度帮助开发者在实施前充分评估可能的影响。
实用代码示例
提供了完整的扩展方法实现,展示了如何通过
Polly
库实现重试机制。这对读者来说是一个可以直接复制粘贴的解决方案。简洁的操作步骤
文章清晰地说明了从添加依赖到使用扩展方法的完整流程,方便开发者快速上手。
改进建议:
生产环境下的最佳实践
appsettings.json
)来控制迁移行为。异常处理的深度
环境敏感性
依赖注入的优化
services.GetRequiredService<ILogger<TContext>>()
获取日志器。可以进一步优化为通过构造函数注入的方式。资源管理
finally
块中释放资源或确保清理操作,即使发生异常也能保证资源正确释放。闪光点:
文章的扩展方法设计简洁而高效,特别是使用
Polly
库来实现重试机制是一个很好的实践。这种代码结构不仅易于维护,还为未来的功能扩展留出了空间。总结
这篇文章提供了一个实用的解决方案,并在潜在风险方面做了充分的警示。通过添加一些额外的安全措施和环境控制,可以进一步提升其实用性和安全性。期待看到作者在未来分享更多关于Entity Framework的最佳实践!
I appreciate your article on "Auto update database for ASP.NET Core with Entity Framework." It provides a detailed and informative explanation of how to automatically update a database when an application starts. The core idea of this blog post is to warn developers about the potential dangers of applying migrations automatically and then provide a solution to do so with caution.
You have done an excellent job of highlighting the risks associated with automatic migrations, such as data loss, working on obsolete branches, and migration failures. Your article emphasizes that applying migration is a dangerous action, and developers should ensure that everything is fine before proceeding with automatic updates.
The inclusion of code snippets and the step-by-step guide on how to enable automatic updates using the Polly library and the extended method for IHost is very helpful. It not only helps readers understand the concept but also enables them to implement the solution in their projects.
One area where the article could be improved is by providing more information on the Polly library and its role in the solution. A brief introduction to the library and its benefits would be helpful for readers who may not be familiar with it. Additionally, mentioning how the retry policy in the code snippet helps handle exceptions and mitigate the risks associated with automatic migrations would be beneficial.
Overall, your article is well-written and informative, and it addresses a significant concern for developers working with ASP.NET Core and Entity Framework. Keep up the great work, and I look forward to reading more of your articles in the future!
Hi, I was very excited, but there is a problem: MigrateDbContext<WikiDbContext>() needs arguments to call the class in Program.cs.
1- .MigrateDbContext<WikiDbContext>()
2 - public static IHost MigrateDbContext<TContext>( this IHost host, Action<TContext, IServiceProvider> seeder = null) where TContext : DbContext
积极向上的