ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • EF Core 테이블 상속 매핑 (TPT)
    .NET/Database 2025. 2. 17. 23:56

    EF core 테이블 상속 매핑 개념 

    Entity Framework Core(이하 EF Core)는 객체 지향 프로그래밍에서 흔히 사용되는 상속 개념을 관계형 데이터베이스(RDB)와 매핑할 수 있는 다양한 전략을 제공합니다. 이 글에서는 EF Core의 테이블 상속 매핑 기법인 Table Per Hierarchy(TPH), Table Per Type(TPT), Table Per Concrete Type(TPC)을 비교하고, 각 전략이 어떤 경우에 적합한지 살펴보겠습니다.

    테이블 상속 방법 

    테이블 상속 방법은 클래스를 상속하는 방법과 다르지 않습니다. 

    using System.ComponentModel.DataAnnotations;
    
    namespace Database.Entity;
    
    public class DocumentBase
    {
        [Key]
        public int Id { get; set; }
        [MaxLength(255)]
        public string Title { get; set; }
        [MaxLength(20)]
        public string CreatedBy { get; set; }
        public DateTime CreatedDate { get; set; }
    }
    
    public class GeneralDocumentBase : DocumentBase
    {
        [MaxLength(255)]
        public string Content { get; set; }
    }
    
    public class ContractDocumentBase : DocumentBase
    {
        [MaxLength(255)]
        public string ContractorName { get; set; }
        public DateTime ExpirationDate { get; set; }
    }
    
    public class TechnicalDocumentBase : DocumentBase
    {
        [MaxLength(255)]
        public string TechnologyUsed { get; set; }
        public int Version { get; set; }
    }

    위와 같이 부모 클래스를 정의하고 이를 상속받는 자식클래스를 만듭니다.

    상속하는 방식에 대한 것은 일반 클래스와 크게 다르지 않지만, 이것을 각 EFCore의 매핑방식에 테이블에 각각 다르게 적용 되는 것을 확인 할 수 있습니다. 

     

    이 포스트에서는 부모 테이블과 자식 테이블을 모두 생성하고, 부모테이블에서 생성된 키를 통해서 모델을 공유할 수 있는 TPT에 대해서 진행해보도록 하겠습니다.

    TPT(Table Per Type)

    public partial class ShopDbContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
        
        public DbSet<DocumentBase> Documents { get; set; }
        
        public DbSet<TechnicalDocumentBase> TechnicalDocuments { get; set; }
        
        public DbSet<GeneralDocumentBase> GeneralDocuments { get; set; }
        
        public DbSet<ContractDocumentBase> ContractDocuments { get; set; }
        
        public ShopDbContext(DbContextOptions<ShopDbContext> options) 
            :base(options)
        {
            
        }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            
        }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<DocumentBase>()
                .UseTptMappingStrategy()
                .ToTable("Documents");
        }
    }

    위에서 만든 DocumentBase 클래스를 상속받는 클래스와, DocumentBase가 매핑 될 테이블을 DbSet<T> 멤버로 정의하고,

    OnModelCreating 함수에서 DocumentBase 클래스가 Tpt 전략을 취하고 있고 대상테이블이 Documents 테이블 이라는 것을 지정 합니다. 이렇게 되면 DocumentBase타입을 상속받는 테이블에 대해서는 DocumentBase의 PK를 FK로 받는 형식으로 테이블이 생성됩니다. 

     

    dotnet ef migrations add document
    dotnet ef database update

    Migrator.csproj가 위치한 폴더에서 위 명령을 실행합니다. 

    위 사진과 같이 Documents와 상속받은 테이블들이 생성된 것을 확인 할 수 있습니다. 

    여기서 ContractDocuments 테이블에 데이터를 추가해보겠습니다. 

    var context= service.GetRequiredService<ShopDbContext>();
    context.ContractDocuments.Add(new ContractDocumentBase
    {
        Id = 0,
        Title = "test",
        CreatedBy = "null",
        CreatedDate = default,
        ContractorName = "null",
        ExpirationDate = default
    });
    
    await context.SaveChangesAsync();

    콘솔에서 실행된 쿼리를 확인해보면 코드상에서는 ContractDocuments 테이블에만 삽입하였지만, 실제 데이터는 Documents 테이블과 ContractDocuments 테이블 양측에 데이터가 추가된 것을 볼수 있습니다.

     

    이러한 테이블 매핑은 위 예제와 같이 부모테이블을 만들고 공통적인 데이터들을 사용하는 자식테이블들을 추가한뒤 자식테이블들의 키값을 주소테이블에서 처리하고자 할때 유용할 것으로 보입니다. 

     

    위 예제에서는 일반클래스로 Document가 지정되어 Documents 테이블에 직접 넣는 것이 가능하지만 abstract class로 지정하게되면 부모테이블에는 직접 데이터 추가를 하지 못하도록 지정할 수도 있습니다. 

     

    마무리

    이번 포스트에서는 EF Core의 TPT(Table Per Type) 전략에서 베이스 테이블의 데이터 삽입 동작을 살펴보았습니다.
    콘솔에서 실행된 쿼리를 확인해보면 자식 테이블(예: ContractDocuments)에 데이터가 삽입될 때, 자동으로 부모 테이블(Documents)에도 데이터가 추가됨을 확인할 수 있습니다.

     

    이러한 테이블 매핑 방식은 부모 테이블을 활용하여 공통 속성을 관리하고, 개별적인 데이터를 자식 테이블에서 처리할 때 매우 유용합니다.

     

    특히 주소 관리, 계약 문서 관리, 제품 카테고리 등 공통 데이터를 공유하는 다양한 도메인 모델링에 활용할 수 있습니다.

    또한, 부모 클래스(Document)를 일반 클래스로 정의하면 직접 삽입이 가능하지만, abstract class로 선언하면 직접 삽입이 불가능해져 더욱 강력한 데이터 무결성을 유지할 수 있습니다.
    이러한 특징을 활용하면 TPT를 적용한 테이블 설계를 더욱 안정적이고 효과적으로 운영할 수 있습니다.

     

     

    '.NET > Database' 카테고리의 다른 글

    EF Core 테이블 상속 매핑 (TPH)  (0) 2025.03.10
    EF Core 테이블 상속 매핑(TPC)  (0) 2025.03.10
    EF Core - (부록) Project Setup  (0) 2025.02.03
    EF Core - Code First  (0) 2025.01.11
    EF Core - Domain 분리구조 만들기  (0) 2024.03.22
Designed by Tistory.