ASP.NET MVC 6 응용 프로그램이 Database.EnsureCreated
있고 및 Database.Migrate
메서드 를 호출해야 합니다.
하지만 어디로 전화해야합니까?
답변
나는 이것이 중요한 질문이고 잘 대답되어야한다고 생각합니다!
Database.EnsureCreated 란 무엇입니까?
context.Database.EnsureCreated()
컨텍스트에 대한 데이터베이스가 존재하는지 확인하는 새로운 EF 핵심 방법입니다. 존재하는 경우 조치가 수행되지 않습니다. 존재하지 않는 경우 데이터베이스와 모든 스키마가 생성되고이 컨텍스트의 모델과 호환되는지 확인합니다.
참고 :
이 방법은 마이그레이션을 사용하여 데이터베이스를 생성하지 않습니다. 또한 생성 된 데이터베이스는 나중에 마이그레이션을 사용하여 업데이트 할 수 없습니다. 관계형 데이터베이스를 대상으로하고 마이그레이션을 사용하는 DbContext.Database.Migrate()
경우이 방법을 사용하여 데이터베이스가 생성되고 모든 마이그레이션이 적용되는지 확인할 수 있습니다 .
EF 6으로 어떻게 했습니까?
context.Database.EnsureCreated()
EF 6의 아래 나열된 접근 방식과 동일합니다.
-
패키지 관리자 콘솔 :
Enable-Migrations -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 ()를 사용하십시오.
답변
James P와 Bassam Alugili가 제공 한 정보를 사용하여 결국이 코드 줄을 클래스 ( Startup.cs ) 의 Configure
메서드에 추가했습니다 .Startup
using (var scope =
app.ApplicationServices.CreateScope())
using (var context = scope.ServiceProvider.GetService<MyDbContext>())
context.Database.Migrate();
답변
앞서 언급 한 것처럼 Rowan Miller의 다음 내용을 읽어야 합니다 .
…
EnsureCreated
마이그레이션을 완전히 우회하고 스키마를 생성합니다. 마이그레이션과 혼합 할 수 없습니다.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();
}
답변
일반적으로는 다음과 같이 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는 여기 에서 시작하는 동안 서비스를 수동으로 해결하는 방법에 대해 설명 하지만 다음과 같이 언급합니다.
서비스를 수동으로 해결 (서비스 로케이터라고도 함)하는 것은 일반적으로 안티 패턴으로 간주됩니다 . [그리고] 가능한 한 피해야합니다.
Henk는 또한 Startup
생성자의 종속성 주입이 매우 제한적이며에서 구성된 서비스를 포함하지 않기 Startup.ConfigureServices()
때문에 DbContext 사용이 앱의 나머지 부분에서 사용되는 주입 컨테이너를 통해 가장 쉽고 적절하다고 언급합니다.
런타임의 호스팅 서비스 공급자는 , ( 3.0 이전 버전) 및 .NET
Startup
과 같은 특정 서비스를 클래스 생성자에 삽입 할 수 있습니다 . 후자는 호스팅 계층에 의해 구축 된 인스턴스이며 애플리케이션을 시작하는 데 필요한 필수 서비스 만 포함합니다.IConfiguration
IWebHostEnvironment
IHostingEnvironment
ILoggerFactory
IServiceProvider
주문 전화에서 Database.EnsureCreated()
또는 Database.Migrate()
, 우리가 할 수있는, 그리고에 자동으로 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();
}
}
}
로 기억하십시오 바삼 Alugili의 대답 것을 EF 코어 문서에서 참조 Database.EnsureCreated()
와 Database.Migrate()
하나 개의 보장하지만 기존 마이그레이션이 필요한 경우 생성 된 데이터베이스에 적용되기 때문에 함께 사용되는 것은 아니다. 다른 하나는 데이터베이스가 존재하는지 확인하고 그렇지 않은 경우 DbContext
컨텍스트에서 Fluent API를 통해 수행 된 시드를 포함하여 를 반영하는 데이터베이스를 생성합니다 .
답변
또한 컨텍스트의 생성자에서 이것을 호출하면 성능 저하를 볼 수 있습니다 EnsureCreated
. setup.cs 유틸리티로 이동 한 후 응답 시간이 크게 향상되었습니다.
참고 : EFC 및 UWP를 사용하고 있습니다.