如何以及在哪里调用 Database.EnsureCreated 和 Database。迁移?

我有一个 ASP.NET MVC 6应用程序,我需要调用 Database.EnsureCreatedDatabase.Migrate方法。

但是我应该在哪里打电话给他们呢?

106048 次浏览

作为前言,你应该读一读罗文 · 米勒(Rowan Miller)的 这个:

... EnsureCreated完全绕过迁移,只是创建 对于您来说,模式不能与迁移混合使用 设计用于测试或快速成型 每次删除和重新创建数据库。如果您正在使用 移植,并希望在应用程序启动时自动应用它们, 然后你可以用 context.Database.Migrate()代替。

根据 给你的答案,你需要把 Globals.EnsureDatabaseCreated();加到 Startup.cs:

Startup.cs的启动功能:

public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();


if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
Globals.Configuration = Configuration;
Globals.HostingEnvironment = env;
Globals.EnsureDatabaseCreated();
}

Globals.EnsureDatabaseCreated()的定义如下:

public static void EnsureDatabaseCreated()
{
var optionsBuilder = new DbContextOptionsBuilder();
if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:DataContext"]);
else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:DataContext"]);
else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:DataContext"]);
var context = new ApplicationContext(optionsBuilder.Options);
context.Database.EnsureCreated();


optionsBuilder = new DbContextOptionsBuilder();
if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:TransientContext"]);
else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:TransientContext"]);
else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:TransientContext"]);
new TransientContext(optionsBuilder.Options).Database.EnsureCreated();
}

要使用 context.Database.Migrate(),请参阅 给你给你

我认为这是一个很重要的问题,应该得到很好的回答!

什么是数据库?

context.Database.EnsureCreated()是一种新的 EF 核心方法,它确保上下文数据库的存在。如果它存在,就不会采取任何行动。如果它不存在,那么将创建数据库及其所有模式,并确保它与此上下文的模型兼容。

注: 此方法不使用迁移创建数据库。此外,创建的数据库以后不能使用迁移进行更新。如果你的目标是一个关系数据库并且使用迁移,你可以使用 DbContext.Database.Migrate()方法来确保数据库被创建并且所有的迁移都被应用。

我们是怎么做到的?

context.Database.EnsureCreated()相当于外汇基金6的下列办法:

  1. 软件包管理器控制台:

    启用-迁移-启用自动迁移。添加-迁移/更新-数据库。

  2. 源自代码:

    创建 DatabaseIfNotExists

或者

使用 DbMigationsConfiguration 并设置 AutomaticMigationsEnable = true;

什么是数据库。迁移?

将上下文的任何挂起的迁移应用到数据库。如果数据库不存在,将创建该数据库。

我们是怎么做到的?

context.Database.Migrate()相当于外汇基金6的下列办法:

  1. 软件包管理器控制台:

    更新-数据库-目标迁移

  2. 使用自定义 DbMigationsConfiguration:

    自动迁移启用 = false; 或使用 DbMigator。

结论 :

如果您正在使用迁移,那么有 context.Database.Migrate()。如果您不想要迁移,只想要一个快速的数据库(通常用于测试) ,那么使用上下文。数据库。EnsureCreated ()/EnsureDelete ().

根据 James P 和 Bassam Alugili 提供的信息,我最终将这些代码行添加到 Startup类(Startup.cs)的 Configure方法中:

using (var scope =
app.ApplicationServices.CreateScope())
using (var context = scope.ServiceProvider.GetService<MyDbContext>())
context.Database.Migrate();

此外,如果您在上下文的构造函数中调用这个函数,您可能会看到性能下降... ... 在将 EnsureCreated移动到 setup.cs 实用程序之后,我注意到响应时间有了相当大的改进。

注意: 我使用的是 EFC 和 UWP。

通常情况下,DbContext会被添加到 Startup.ConfigureServices()的依赖注入容器中,如下所示:

public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}


public IConfiguration Configuration { get; }


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add DbContext to the injection container
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
this.Configuration.GetConnectionString("DefaultConnection")));
}
}

然而,IServiceCollection并不是一个服务提供者,而且由于 DbContext没有在当前范围(Startup.ConfigureServices)的注入容器 之前中注册,我们无法通过依赖注入访问上下文。

Henk Mollema 讨论了在启动 给你期间手动解析服务,但是提到..。

手动解析服务(又名服务定位器)通常是 < a href = “ https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern”rel = “ noReferrer”> 考虑使用反模式 ... [并且]应该尽量避免使用它 越多越好。

Henk 还提到,Startup构造函数的依赖注入非常有限,并且不包括在 Startup.ConfigureServices()中配置的服务,所以通过应用程序其余部分使用的注入容器,使用 dbContext 是最简单和最合适的。

运行时的宿主服务提供者可以将某些服务注入到 Startup类的构造函数中,例如 IConfigurationIWebHostEnvironment(3.0以前版本中的 IHostingEnvironment)、 ILoggerFactoryIServiceProvider。请注意,后者是由宿主层构建的实例,只包含启动应用程序所需的基本服务。

为了调用 Database.EnsureCreated()Database.Migrate(),我们可以并且希望在 Startup.Configure()中自动解析 DbContext,在 Startup.Configure()中我们配置的服务现在可以通过 DI 访问:

public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}


public IConfiguration Configuration { get; }


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add DbContext to the injection container
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
this.Configuration.GetConnectionString("DefaultConnection")));
}


public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyDbContext context)
{
if (env.IsDevelopment())
{
context.Database.EnsureCreated();
//context.Database.Migrate();
}
}
}

请记住,从 EF Core 文档中引用的 巴萨姆 · 阿卢吉利的回答中,Database.EnsureCreated()Database.Migrate()不应该一起使用,因为它们可以确保将现有的迁移应用到数据库中,如果需要,数据库会创建。另一个只是确保数据库存在,如果不存在,则创建一个反映 DbContext的数据库,包括在上下文中通过 Fluent API 完成的任何种子化操作。

var builder = WebApplication.CreateBuilder(args);


// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddDbContext<YourDbContext>(option => option.UseSqlServer(@"Data source=(localdb)\ProjectModels;Initial Catalog=YourDb;Integrated Security=True"));


var app = builder.Build();


// Configure the HTTP request pipeline.
YourDbContext dbcontext = app.Services.GetRequiredService<YourDbContext>();
dbcontext.Database.EnsureCreated();

如果您使用的是 VS 2022/。网络版本6和您正在尝试找到一种方法来创建您的数据库。.那么

执行以下步骤

通过包管理器添加 Microsoft.EntityFramework.Tools 引用 从包管理器控制台

运行步骤1

Add-迁移初始迁移

这里初始化移植是自定义名称,您可以键入任何您想要的. 。 让它跑起来

第二步

更新-资料库

这将创建您的数据库。