Entity class & Table Mapping

Eunho Bae·2022년 7월 1일
0

주제

Entity와 DB Table 간 연동하는 다양한 방법들에 대해 알아보자
Entity class 하나를 통으로 Read/Write하는 것은 부담이 되기 때문에 이전 시간에 Select Loading, DTO를 활용했었다. 하지만 이 외에도 기본적인 방법들이 몇가지 존재한다.

Owned Type

일반 class를 entity class에 추가하는 개념

    public class ItemOption
    {
        public int Str { get; set; }
        public int Dex { get; set; }
        public int Hp { get; set; }
    }

    [Table("Item")]
    public class Item
    {
       public ItemOption Option { get; set; }

Option을 설정하는 여러가지 방법이 있다.

동일한 테이블에 추가

AppDbContext

        protected override void OnModelCreating(ModelBuilder builder)
        {
            // 이 타입을 별도의 테이블로 분리해서 관리하는게 아니라 자신의 테이블에 포함하고 싶을 경우
            builder.Entity<Item>()
                .OwnsOne(i => i.Option); // Option_Str, Option_Dex, Option_Hp 열이 추가됨
        }

DbCommands

            item[0].Option = new ItemOption() { Dex = 1, Hp = 2, Str = 3 };

이렇게 동일한 테이블에 추가하는 방식으로 하면 나중에 Option 정보만 추출하고 싶을때 Item entity class의 Option에 접근하여 간편하게 추출할 수 있다.

예제


다른 테이블에 추가

            builder.Entity<Item>()
                .OwnsOne(i => i.Option)
                .ToTable("ItemOption");

Table Per Hierarchy (TPH)

상속 관계의 여러 class <-> 하나의 테이블에 매핑

Convention

DataModel

    public class EventItem : Item // 기간제 아이템
    {
        public DateTime DestroyDate { get; set; }
    }

AppDbContext

        public DbSet<Item> Items { get; set; } 
        public DbSet<EventItem> EventItems { get; set; } 

위와 같이 코딩하면 EventItem 테이블이 따로 생성되지 않고, DestroyDate 열이 Item 테이블에 하나 추가된 것을 볼 수 있다. 행마다 Item인지 EventItem인지 구분하는 것은 Discriminator 열이 따로 추가되어서 Item이면 Item으로 세팅되어 있는 것을 볼 수 있다.

Fluent API

ItemType enum을 Discriminator로 사용할 수 있다.

DataModel

 public class ItemOption
    {
        public int Str { get; set; }
        public int Dex { get; set; }
        public int Hp { get; set; }
    }

    public enum ItemType
    {
        NormalItem,
        EventItem
    }

    public class Item
    {
        public ItemType Type { get; set; }
       public ItemOption Option { get; set; }

		...
    }

    public class EventItem : Item // 기간제 아이템
    {
        public DateTime DestroyDate { get; set; }
    }

AppDbContext


        public DbSet<Item> Items { get; set; } 
        //public DbSet<EventItem> EventItems { get; set; } 

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Item>()
                .OwnsOne(i => i.Option)
                .ToTable("ItemOption");

            builder.Entity<Item>()
                .HasDiscriminator(i => i.Type) // Type을 구분자로 사용할 것이다.
                .HasValue<Item>(ItemType.NormalItem) // Item은 NormalItem으로 넣어달라  
                .HasValue<EventItem>(ItemType.EventItem);
        }

DbCommands

 			List<Item> items = new List<Item>()
            {
                new Item()
                {
                    TemplateId = 101,
                    CreateDate = DateTime.Now,
                    Owner = strevelun,
                },
                new EventItem()
                {
                    TemplateId = 102,
                    CreateDate = DateTime.Now,
                    Owner = rookiss,
                    DestroyDate = DateTime.Now,
                },
                
                new Item()
                {
                    TemplateId = 103,
                    CreateDate = DateTime.Now,
                    Owner = faker,
                }
            };
            
            ...
            
            
            EventItem eventItem = item as EventItem; // EventItem 타입이 아니면 null 반환
            if(eventItem != null)
                Console.WriteLine("DestroyDate : " + eventItem.DestroyDate);
            

Table Splitting

다수의 Entity class <-> 하나의 테이블에 매핑

AppDbContext

            builder.Entity<Item>()
                .HasOne(i => i.Detail)
                .WithOne()
                .HasForeignKey <ItemDetail>(i => i.ItemDetailId);

            builder.Entity<Item>().ToTable("Items");
            builder.Entity<ItemDetail>().ToTable("Items");
    public class ItemDetail
    {
        public int ItemDetailId { get; set; }
        public string Description { get; set; }
    }

    public class Item
    {
        public ItemDetail Detail { get; set; }
profile
개인 공부 정리

0개의 댓글