Entity Framework Core에서 데이터베이스 자동 생성


100

.NET Core로 포팅되는 내 애플리케이션은 SQLite와 함께 새로운 EF Core를 사용합니다. 앱이 처음 실행될 때 자동으로 데이터베이스 및 테이블 구조를 만들고 싶습니다. EF 핵심 문서에 따르면 수동 명령을 사용하여 수행됩니다.

dotnet ef migrations add MyFirstMigration

dotnet ef database update

그러나 최종 사용자가 이러한 명령을 입력하는 것을 원하지 않으며 앱에서 처음 사용할 데이터베이스를 만들고 설정하는 것을 선호합니다. EF 6의 경우 다음과 같은 기능이 있습니다.

Database.SetInitializer(new CreateDatabaseIfNotExists<MyContext>());

그러나 EF Core에서는 존재하지 않는 것 같습니다. EF 코어와 동등한 것에 대한 예제 나 문서를 찾을 수 없으며 EF 코어 문서의 누락 된 기능 목록에 언급되어 있지 않습니다. 모델 클래스가 이미 설정되어 있으므로 모델을 기반으로 데이터베이스를 초기화하는 코드를 작성할 수 있지만 프레임 워크가이를 자동으로 수행하면 힙이 더 쉬울 것입니다. 모델을 자동으로 빌드하거나 마이그레이션하지 않고 새 데이터베이스에 테이블 구조를 만듭니다.

여기에 뭔가 누락되었거나 EF 코어에서 자동 생성 테이블 함수가 누락 되었습니까?

답변:


146

마이그레이션을 만든 경우 다음과 같이 Startup.cs 에서 실행할 수 있습니다.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 {
      using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
      {
            var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.Migrate();
      }

      ...

그러면 추가 된 마이그레이션을 사용하여 데이터베이스와 테이블이 생성됩니다.

Entity Framework 마이그레이션을 사용하지 않고 대신 처음 실행할 때 컨텍스트 클래스에있는 그대로 DbContext 모델을 생성해야하는 경우 다음을 사용할 수 있습니다.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 {
      using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
      {
            var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.EnsureCreated();
      }

      ...

대신.

데이터베이스가 생성되었는지 확인하기 전에 데이터베이스를 삭제해야하는 경우 다음을 호출하십시오.

            context.Database.EnsureDeleted();

전화하기 직전에 EnsureCreated()

수정 : http://docs.identityserver.io/en/latest/quickstarts/7_entity_framework.html?highlight=entity


1
나는 여전히 EF를 처음 접했고 현재 데이터베이스 파일을 사용하여 Visual Studio에서 먼저 "데이터베이스에서 생성"EF 6 코드를 사용하여 데이터 구조를 정의하는 클래스를 만들었습니다. 그런 다음이를 새로운 dotnet core VS 솔루션에 잘라내어 붙여 넣었습니다. 따라서 마이그레이션이 아닌 것 같습니다. 위 코드를 사용하기 전에 마이그레이션 파일을 만들어야 함을 의미합니까?
deandob

2
명령 context.Database.EnsureCreated () / EnsureDeleted ()에서 자세한 내용 사용할 수 있습니다, 마이그레이션을 사용하지 않는 경우 난`미안, 나는 내 대답에 실수를했다 blogs.msdn.microsoft.com/dotnet/2016을 / 09 / 29 /…
Ricardo Fontana

2
두 가지 솔루션이 모두 필요한 경우 어떻게합니까? 방금 앱을 UWP로 포팅하고 EF Core를 사용하기 시작했습니다. 즉, 일부 사용자는 DB를 처음부터 만들어야하고 다른 사용자는 이미 DB를 가지고 있습니다. 첫 번째 마이그레이션에서 초기 테이블이 아직 존재하지 않는 경우에만 생성되도록하는 방법이 있습니까? 당신의 대답이 이것을 다루지 않는 것 같거나 내가 뭔가를 놓치고 있습니까?
Lars Udengaard

33

내 대답은 Ricardo의 대답과 매우 유사하지만 그의 using기능 에 너무 많은 일이 일어나서 낮은 수준에서 정확히 어떻게 작동하는지조차 확신하지 못 하기 때문에 내 접근 방식이 조금 더 간단하다고 느낍니다 .

따라서 내부에서 무슨 일이 일어나고 있는지 정확히 알고있는 데이터베이스를 생성하는 간단하고 깨끗한 솔루션을 원하는 사람들을 위해 다음과 같이하십시오.

public Startup(IHostingEnvironment env)
{
    using (var client = new TargetsContext())
    {
        client.Database.EnsureCreated();
    }
}

이것은 DbContext당신이 만든 (이 경우 내 이름은라고 함 TargetsContext)의 인스턴스를 사용하여 Startup.cs 가 애플리케이션에서 실행될 DbContext때 클래스에 정의 된 테이블이 생성 되도록 할 수 있음을 의미합니다.


10
여기에 있는 정보처럼 : EnsureCreated마이그레이션을 완전히 우회하고 스키마를 생성하기 만하면됩니다. 마이그레이션과 혼합 할 수 없습니다. EnsureCreated매번 데이터베이스를 삭제하고 다시 생성해도 괜찮은 테스트 또는 신속한 프로토 타이핑을 위해 설계되었습니다. 마이그레이션을 사용 중이고 앱 시작시 자동으로 적용되도록하려면 context.Database.Migrate()대신 사용할 수 있습니다 .
Thomas Schneiter

이것은 내 연결 문자열이 작동하지 않는 이유에 대한 내 혼란에 대한 대답입니다 ... :( 그래서 데이터베이스가 자동으로 생성되지 않으므로 DbContext 생성자에서 수행 한 Database.EnsureCreated ()를 지정해야합니다. 감사합니다. 3 일 딜레마에서 저를 구해줍니다. X_X
pampi

방금 시작 파일에 붙여 넣으려고했는데 VS2019 IHostingEnvironment가 이제 더 이상 사용되지 않으며 권장되는 대안은 Microsoft.AspNetCore.Hosting.IWebHostEnvironment.
ctrl-z pls

18

Startup.cs의 Configure 매개 변수 목록을 통해 컨텍스트를 얻는 경우 대신 다음을 수행 할 수 있습니다.

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  LoggerFactory loggerFactory,
    ApplicationDbContext context)
 {
      context.Database.Migrate();
      ...

1
IMHO 이것이 최상의 솔루션입니다. 서비스 나 DB 컨텍스트에 대해 신경 쓸 필요가 없으며 종속성 주입을 통해 얻은 컨텍스트를 사용할 수 있습니다. 좋은!
Tobias

12

EF Core 2.0+의 경우 API를 변경했기 때문에 다른 접근 방식을 취해야했습니다. 2019 년 3 월부터 Microsoft는 애플리케이션 엔트리 클래스에 WebHost 빌드 코드 외부에 데이터베이스 마이그레이션 코드를 넣는 것이 좋습니다 .

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();
        using (var serviceScope = host.Services.CreateScope())
        {
            var context = serviceScope.ServiceProvider.GetRequiredService<PersonContext>();
            context.Database.Migrate();
        }
        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

7

마이그레이션을 생성하지 않은 경우 두 가지 옵션이 있습니다.

1. 응용 프로그램 Main에서 데이터베이스 및 테이블을 만듭니다.

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();

2. 데이터베이스가 이미있는 경우 테이블을 만듭니다.

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();

Bubi의 답변 덕분에


2
당신의 서비스는 무엇입니까?
MichaelMao

모든 I "는 사용하지 마십시오 말을 마이그레이션 주위에 쇼에게 큰 뚱뚱한 경고를 읽고 있어요 문서 EnsureCreatedEnsureDeleted또는 Database.Migrate실패 할 것"
mwilson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.