본문 바로가기
Entity Framework Core

Entity Framework Core] Reverse engineering (scaffolding)

by Fastlane 2023. 7. 25.
728x90
반응형

예시 명령어는 .NET CLI 기준으로 작성했다. 

Database Schemas 관리

EF Core는 EF Core model과 database schema 사이에 sync를 유지하기 위해, 2가지 방법을 제공한다. 둘 중 선택하려면, EF Core model과 database schema 중 기준이 되는 것을 정해야 한다. 

 

EF Core model이 기준이라면, Migrations을 사용해야 한다. EF Core model을 수정하면서 database에도 동일하게 적용해야 한다. 

 

database schema가 기준이라면, Reverse Engineering을 사용한다.  

 

Reverse engineering

database schema 기준으로 entity type classes와 DbContext class를 생성한다. VS Studio EF Core PMC에서는 Scaffold-DbContext 명령어를 사용하고, .NET CLI에서는 dotnet ef dbcontext scaffold 명령어를 사용한다. 

 

Visual Studio를 사용한다면 EF Core Power Tools 이라는 무료 오픈소스 VS Extension을 사용해볼 수 있다. 

https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools 

 

 

설치사항

  • VS Studio를 사용한다면 PMC tools 설치, 아니면 .NET CLI tools 설치
  • Microsoft.EntityFrameworkCore.Design package 설치
  • 사용하려는 db schema에 맞는 database provider package 설치 

필수 Arguments

PMC, .NET CLI 모두 2개의 arguments가 필요하다. connection string과 사용할 EF Core database provider

dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer

 

명령어 옵션

테이블, 뷰 지정하기

기본적으로, db schema의 모든 테이블과 뷰가 entity types으로 스캐폴딩된다. schema와 테이블을 지정하므로 스캐폴딩 될 테이블과 뷰를 제한할 수 있다. 

 

만약에 Artists, Album 테이블만 스캐폴드 하려고 하면

dotnet ef dbcontext scaffold ... --table Artist --table Album

Customer, Contractor schemas의 모든 테이블과 뷰를 스캐폴드 하려고 하면

dotnet ef dbcontext scaffold ... --schema Customer --schema Contractor

Customer schema의 Purchases 테이블, Contractor schema의 Accounts, Contracts 테이블을 스캐폴드 하려고 하면

dotnet ef dbcontext scaffold ... --table Customer.Purchases --table Contractor.Accounts --table Contractor.Contracts

database name 유지

기본적으로, 테이블과 컬럼명은 types, properties.NET naming conventions에 맞게 수정된다. 

예를들어 아래의 테이블을 고려해보자. 

CREATE TABLE [BLOGS] (
    [ID] int NOT NULL IDENTITY,
    [Blog_Name] nvarchar(max) NOT NULL,
    CONSTRAINT [PK_Blogs] PRIMARY KEY ([ID]));

CREATE TABLE [posts] (
    [id] int NOT NULL IDENTITY,
    [postTitle] nvarchar(max) NOT NULL,
    [post content] nvarchar(max) NOT NULL,
    [1 PublishedON] datetime2 NOT NULL,
    [2 DeletedON] datetime2 NULL,
    [BlogID] int NOT NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([id]),
    CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogID]) REFERENCES [Blogs] ([ID]) ON DELETE CASCADE);

기본으로 스캐폴드 하면 아래와 같다. 

public partial class Blog
{
    public int Id { get; set; }
    public string BlogName { get; set; } = null!;
    public virtual ICollection<Post> Posts { get; set; } = new List<Post>();
}

public partial class Post
{
    public int Id { get; set; }
    public string PostTitle { get; set; } = null!;
    public string PostContent { get; set; } = null!;
    public DateTime _1PublishedOn { get; set; }
    public DateTime? _2DeletedOn { get; set; }
    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; } = null!;
}

--use-database-names 옵션을 사용하면 다음과 같다. 

public partial class BLOG
{
    public int ID { get; set; }
    public string Blog_Name { get; set; } = null!;
    public virtual ICollection<post> posts { get; set; } = new List<post>();
}

public partial class post
{
    public int id { get; set; }
    public string postTitle { get; set; } = null!;
    public string post_content { get; set; } = null!;
    public DateTime _1_PublishedON { get; set; }
    public DateTime? _2_DeletedON { get; set; }
    public int BlogID { get; set; }
    public virtual BLOG Blog { get; set; } = null!;
}

mapping attributes (Data Annotations) 사용하기 

기본적으로, OnModelCreating으로 구성된다. --data-annotations 옵션을 사용해서 가능한 경우에,  mapping attributes를 사용하도록 할 수 있다. 

 

DbContext name

기본으로 db이름에 Context가 붙는 이름으로 되지만, 지정하고 싶으면 --context 옵션을 사용한다. 

 

디렉토리, namespace 지정

--context-dir, --output-dir, --namespace, --context-namespace

 

커스터마이징 코스 

스캐폴딩으로 코드 생성된 이후, 변경될 수 있다. database model이 변경되었을 때, 다시 스캐폴딩 프로세스를 재실행할지 여부에 따라 커스터마이징 방법이 달라진다. 

 

한번만 스캐폴딩 할때

스캐폴드된 코드는 code-base mapping의 시작점이 된다. 어떤 코드 수정도 가능하다. 

database와 EF model의 sync를 유지할 수 있는 두가지 방법이 있다. 

  • EF Core database migrations를 사용하는 것으로 변경한다. 
  • db가 변경되었을때, 수동으로 entity type과 EF configuration을 수정한다.

여러번 스캐폴딩 할때

DB변경 시마다, 다시 스캐폴딩한다. 전에 생성된 스캐폴드 코드를 덮어쓴다. 즉 수정사항이 손실될 수 있다.

기본으로 덮어쓰지 않지만, --force 옵션으로 기존 파일을 덮어쓸 수 있다. 

 

덮어쓸 수 있기 때문에, 직접 수정하는 것은 좋지 않다. 하지만 partial classes와 methods을 사용할 수 있다. 그리고 EF Core는 override를 허용한다. 

 

 

 

 

728x90
반응형

댓글