我有一个ASP.NET MVC 6应用程序,我需要调用Database.EnsureCreated和Database.Migrate方法。
但我应该在哪里打电话给他们?
答案 0 :(得分:57)
我认为这是一个重要的问题,应该得到很好的回答!
什么是Database.EnsureCreated?
context.Database.EnsureCreated()
是新的EF核心方法,可确保上下文的数据库存在。如果存在,则不采取任何措施。如果它不存在,则创建数据库及其所有模式,并确保它与此上下文的模型兼容。
注意:的
此方法不使用迁移来创建数据库。此外,以后无法使用迁移更新创建的数据库。如果您要定位关系数据库并使用迁移,则可以使用DbContext.Database.Migrate()
方法确保创建数据库并应用所有迁移。
我们是如何使用EF 6做到的?
context.Database.EnsureCreated()
等同于下面列出的EF 6的方法:
软件包管理器控制台:
启用 - 迁移-EnableAutomaticMigrations。添加迁移/更新的数据库。的
来自代码:
Database.SetInitializer CreateDatabaseIfNotExists
或
使用DbMigrationsConfiguration并设置AutomaticMigrationsEnabled = true;
什么是Database.Migrate?
将上下文的任何挂起的迁移应用于数据库。如果数据库尚不存在,将创建数据库。
我们是如何使用EF 6做到的?
context.Database.Migrate()
等同于下面列出的EF 6的方法:
软件包管理器控制台:
更新 - 数据库-TargetMigration
使用自定义DbMigrationsConfiguration:
AutomaticMigrationsEnabled = false;或者使用DbMigrator。
<强>结论强>:
如果您使用迁移,则context.Database.Migrate()
。如果您不想迁移并且只想要一个快速数据库(通常用于测试),那么请使用context.Database.EnsureCreated()/ EnsureDeleted()。
答案 1 :(得分:11)
根据James P和Bassam Alugili提供的信息,我最终做的是将这行代码添加到Startup.cs-&gt; Configure方法中。
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
.CreateScope())
{
serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
.Database.Migrate();
}
答案 2 :(得分:10)
正如前言你应该阅读Rowan Miller的this:
...
EnsureCreated
完全绕过迁移并创建了 架构适合您,您不能将其与迁移混合使用。EnsureCreated
是 专为测试或快速原型设计而设计 每次都删除并重新创建数据库。如果你正在使用 迁移并希望在app start上自动应用它们, 那么你可以改用context.Database.Migrate()
。
根据回答here,您需要将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();
}
答案 3 :(得分:7)
通常,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
尚未在当前作用域 之前注册到注入容器中({{1 }}),我们不能在这里通过依赖注入来访问上下文。
Henk Mollema讨论了在启动here期间手动解决服务的问题,但提到了...
手动解析服务(又称服务定位器)为generally considered an anti-pattern ... [并且]您应尽量避免使用它 尽可能。
Henk还提到Startup.ConfigureServices
构造函数的依赖项注入非常有限,并且不包括在Startup
中配置的服务,因此DbContext的用法最简单,并且最适合在其余的其余部分中使用的注入容器。应用程序。
运行时的托管服务提供商可以将某些服务注入
Startup.ConfigureServices()
类的构造函数中,例如Startup
,IConfiguration
(3.0之前的版本为IWebHostEnvironment
),IHostingEnvironment
和ILoggerFactory
。请注意,后者是由托管层构建的实例,并且仅包含用于启动应用程序的基本服务。
为了调用IServiceProvider
或Database.EnsureCreated()
,我们可以并且希望在Database.Migrate()
中自动解析DbContext,现在可以通过DI使用我们已配置的服务:>
Startup.Configure()
请记住,从EF Core文档中引用的Bassam Alugili's answer来看,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();
}
}
}
和Database.EnsureCreated()
不能一起使用,因为这可以确保将现有迁移应用于创建的数据库如果需要的话。另一个只是确保数据库存在,如果不存在,则创建一个反映您的Database.Migrate()
的数据库,包括通过上下文中Fluent API完成的种子。
答案 4 :(得分:0)
此外,如果您在上下文的构造函数中调用它,您可能会看到性能损失...将for i : CGFloat in stride(from: 1.0, through: 40.0, by: 1.0) {
let angle = 2 * .pi / i
print(angle)
}
移动到setup.cs实用程序后,我发现响应时间有了相当大的改进。
注意:我正在使用EFC和UWP。