C# ASP-Core在启动时迁移EF Core SQL DB
是否可以让我的ASP Core Web API确保使用EF Core将数据库迁移到最新的迁移?我知道这可以通过命令行完成,但我想通过编程来完成。您可以使用C# ASP-Core在启动时迁移EF Core SQL DB,c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,是否可以让我的ASP Core Web API确保使用EF Core将数据库迁移到最新的迁移?我知道这可以通过命令行完成,但我想通过编程来完成。您可以使用 db.Database.EnsureCreated(); 使数据库与当前模型保持同步。如果要启用迁移(如果怀疑后续迁移),请使用 db.Database.Migrate(); 并随时间推移放置后续迁移。文档中关于调用db.Database.EnsureCreated()的注释: 请注意,此API不使用迁移来创建数据库。在里面 此外,创建的
db.Database.EnsureCreated();
使数据库与当前模型保持同步。如果要启用迁移(如果怀疑后续迁移),请使用
db.Database.Migrate();
并随时间推移放置后续迁移。文档中关于调用
db.Database.EnsureCreated()的注释:
请注意,此API不使用迁移来创建数据库。在里面
此外,创建的数据库以后无法使用更新
迁移。如果您以关系数据库为目标并使用
迁移时,可以使用DbContext.Database.Migrate()方法
确保创建了数据库并应用了所有迁移
您可能只想调用db.Database.Migrate()
上述声明来源的评论。根据@steamrolla的回答,我将提出以下改进:
public static class EnsureMigration
{
public static void EnsureMigrationOfContext<T>(this IApplicationBuilder app) where T:DbContext
{
var context = app.ApplicationServices.GetService<T>();
context.Database.Migrate();
}
}
publicstaticclass加密
{
公共静态上下文(此IAApplicationBuilder应用程序),其中T:DbContext
{
var context=app.ApplicationServices.GetService();
Migrate();
}
}
这样,您还可以确保不同上下文的迁移,例如,如果您有一个标识数据库
用法:
app.EnsureMigrationOfContext<context>();
app.EnsureMigrationOfContext();
使用下面的代码在以下位置运行迁移
public async void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<YourContext`enter code here`>();
context.Database.Migrate();
}
}
公共异步无效配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
{
使用(var serviceScope=app.ApplicationServices.GetRequiredService().CreateScope())
{
var context=serviceScope.ServiceProvider.GetService();
Migrate();
}
}
根据chintan310的回答,以下是我如何迁移数据库。这确保了将数据库相关任务分离为程序.cs
:
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetService<AppDbContext>();
context.Database.Migrate();
var seeder = scope.ServiceProvider.GetService<AppSeeder>();
seeder.Seed().Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
host.Run();
}
private static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
publicstaticvoidmain(字符串[]args)
{
var host=BuildWebHost(args);
使用(var scope=host.Services.CreateScope())
{
var services=scope.ServiceProvider;
尝试
{
var context=services.GetService();
Migrate();
var seeder=scope.ServiceProvider.GetService();
播种机。播种()。等待();
}
捕获(例外情况除外)
{
var logger=services.GetRequiredService();
logger.LogError(例如,“在数据库中发生错误”);
}
}
host.Run();
}
私有静态IWebHost BuildWebHost(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.UseStartup()
.Build();
我这样做是为了使用EF Core 2.1.2和SQL Server以编程方式进行迁移,基于之前在此处和“”上的回答:
Startup.cs
使用Microsoft.AspNetCore.Builder;
使用Microsoft.AspNetCore.Hosting;
使用Microsoft.Extensions.Configuration;
使用Microsoft.Extensions.DependencyInjection;
使用Microsoft.EntityFrameworkCore;
名称空间MyApp
{
公营创业
{
//…(仅包括相关代码)。。。
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“MyAppContext”));
// ...
}
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
使用(var serviceScope=app.ApplicationServices.CreateScope())
{
var context=serviceScope.ServiceProvider.GetService();
Migrate();
}
// ...
}
}
}
使用此代码的项目是。这是对先前创建扩展方法的答案的轻微更正。它修复了按编写方式抛出的错误
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace MyApp.Extensions
{
public static class IApplicationBuilderExtensions
{
public static void SyncMigrations<T>(this IApplicationBuilder app) where T : DbContext
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<DbContext>();
context.Database.Migrate();
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统文本;
使用Microsoft.AspNetCore.Builder;
使用Microsoft.EntityFrameworkCore;
使用Microsoft.Extensions.DependencyInjection;
命名空间MyApp.Extensions
{
公共静态类IAApplicationBuilderExtensions
{
公共静态void同步迁移(此IAApplicationBuilder应用程序),其中T:DbContext
{
使用(var serviceScope=app.ApplicationServices.GetRequiredService().CreateScope())
{
var context=serviceScope.ServiceProvider.GetService();
Migrate();
}
}
}
}
此代码适用于.NET core 3.0
using (var scope = app.ApplicationServices.CreateScope())
{
var dbContext = scope.ServiceProvider.GetService<T>();
dbContext.Database.Migrate();
}
使用(var scope=app.ApplicationServices.CreateScope())
{
var dbContext=scope.ServiceProvider.GetService();
dbContext.Database.Migrate();
}
这对我在ASP.NET Core 3.1中很有效,在ConfigureServices
方法中注册数据库上下文后,将其作为参数注入Configure
方法
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(x => x.UseSqlite("Data Source=LocalDatabase.db"));
...
}
有关完整代码示例的更多详细信息和链接,请访问我遵循了IStartupFilter
方法,为迁移任何上下文提供了通用方法
public class DataContextAutomaticMigrationStartupFilter<T> : IStartupFilter
where T : DbContext
{
/// <inheritdoc />
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return app =>
{
using (var scope = app.ApplicationServices.CreateScope())
{
scope.ServiceProvider.GetRequiredService<T>().Database.SetCommandTimeout(160);
scope.ServiceProvider.GetRequiredService<T>().Database.Migrate();
}
next(app);
};
}
}
公共类DataContextAutomaticMiggerationStartupFilter:IStartupFilter
其中T:DbContext
{
///
公共操作配置(下一步操作)
{
返回应用=>
{
使用(var scope=app.ApplicationServices.CreateScope())
{
scope.ServiceProvider.GetRequiredService().Database.SetCommandTimeout(160);
scope.ServiceProvider.GetRequiredService().Database.Migrate();
}
下一步(应用程序);
};
}
}
现在,我们可以通过以下方式注册DataContext和迁移:
第一上下文
services.AddDbContext<ConsumerDataContext>(options => options.UseSqlServer(configuration.GetConnectionString("ConsumerConnection")), ServiceLifetime.Transient);
services.AddTransient<IStartupFilter, DataContextAutomaticMigrationStartupFilter<ConsumerDataContext>>();
services.AddDbContext<ConsumerDataContext>(options => options.UseSqlServer(configuration.GetConnectionString("ConsumerConnection")), ServiceLifetime.Transient);
services.AddTransient<IStartupFilter, DataContextAutomaticMigrationStartupFilter<ConsumerDataContext>>();
services.AddDbContext<UserDataContext>(options => options.UseSqlServer(configuration.GetConnectionString("UserConnection")), ServiceLifetime.Transient);
services.AddTransient<IStartupFilter, DataContextAutomaticMigrationStartupFilter<UserDataContext>>();