대형 프로젝트 - C# + 유니티로 만드는 MMORPG 게임 개발/(5) EF Core

Entity Class와 Data Table 연동

monstro 2025. 8. 19. 15:18
728x90
반응형

- 개요

생성한 Entity 클래스Data Table과 연동하는 방법3개로 구성되어 있습니다.

  • 1) Owned Type : 일반 클래스Entity Class에 추가하는 개념
    • Ownership의 개념으로 동작하므로 Relationship과 다르게 .include()가 필요없음 
    • 추가할 Entity Class의 테이블에 추가하는 경우 : .OwnsOne() 사용
    • 다른 Entity Class의 테이블에 추가하는 경우 : .OwnsOne().ToTable("테이블이름") 사용 
  • 2) Table Per Hierarchy(TPH) : 상속 관계여러 Class하나의 테이블에 매핑하는 개념
    • Descriminator 열을 추가하여 여러 엔터티 타입을 구분 
    • Convention으로 구현하는 경우 : class를 상속받아 만들고, DbSet 추가 
    • Fluent API로 구현하는 경우 : .HasDescriminator().HasValue() 사용
  • 3) Table Splitting : 다수의 Entity 클래스하나의 테이블에 매핑하는 개념

 

1) Owned Type 사용예시

1 - 1) DataModel 클래스

...

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

[Table("Item")]
public class Item
{
    // Owned Type 예시
    public ItemOption? Option { get; set; }

    ...
}

 

Item 엔티티 클래스에 추가할 ItemOption 클래스를 위와 같이 추가하였습니다.

 

1 - 2) AppDBContext 클래스

...

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    ...

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

 

OnModelCreating 함수의 로직을 위와 같이 수정하였습니다.

Item 테이블의 ItemOption 클래스새로운 ItemOption 테이블에 저장하도록 로직을 구성하였습니다.

 

1 - 3) DBCommands 클래스

public static void CreateTestData(AppDBContext db)
{
    ...

    // Owned Type 사용 예시
    items[0].Option = new ItemOption() { Str = 100, Dex = 100, Hp = 100 };

    ...

    db.SaveChanges();
}

 

CreateTestData 함수를 위와 같이 수정하였습니다.

따라서 Item 테이블첫 번째 아이템ItemOption의 데이터를 위와 같이 생성합니다.

 

1 - 4) 실행결과

데이터 테이블 생성

 

데이터 테이블의 구성

 

생성된 데이터 테이블의 실제 데이터

 

위와 같이 ItemOption 데이터 테이블이 생성된 것을 확인할 수 있습니다.

이때 Owned Type 방식으로 생성하여 Item의 PKItemOption의 PK로 지정된 것을 확인할 수 있습니다.

 

2) Table Per Hierachy(TPH) 사용예시

2 - 1) DataModel 클래스

public enum ItemType
{ 
    NormalItem,
    EventItem,
}

[Table("Item")]
public class Item
{
    // TPH 사용예시
    public ItemType Type { get; set; }  

    ...
}

public class EventItem : Item
{ 
    public DateTime DestroyDate { get; set; }
}

 

Item 클래스로부터 상속된 EventItem 클래스를 추가하였습니다.

Item을 구분하기 위한 열거형ItemType을 추가하여 아이템을 구분합니다.

 

2 - 2) AppDBContext 클래스

...

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    ...

    // TPH 사용예시
    modelBuilder.Entity<Item>()
        .HasDiscriminator(i => i.Type)
        .HasValue<Item>(ItemType.NormalItem)
        .HasValue<EventItem>(ItemType.EventItem);
}

 

OnModelCreating 함수의 로직을 위와 같이 수정하였습니다.

Fluent-API 방식으로 Discriminator를 추가하여 Entity의 타입을 구분합니다.

이때 ItemType에 따라 NormalItemEventItem으로 구분합니다.

 

2 - 3) DBCommands 클래스

public static void CreateTestData(AppDBContext db)
{
    ...

    List<Item> items = new List<Item>()
    {
        new Item()
        {
            TemplateId = 101,
            CreateDate = DateTime.Now,
            Owner = Kim
        },
        // TPH 사용예시
        new EventItem()
        {
            TemplateId = 102,
            CreateDate = DateTime.Now,
            Owner = Choi,
            DestroyDate = DateTime.Now
        },
        new Item()
        {
            TemplateId = 103,
            CreateDate = DateTime.Now,
            Owner = Park
        }
    };

    ...

    db.SaveChanges();
}

 

CreateTestData 함수를 위와 같이 수정하였습니다.

Item 데이터 테이블두 번째 아이템을 EventItem으로 생성하도록 수정합니다.

 

2 - 4) 실행결과

TPH로 상속 관계의 Entity 클래스를 부모 Entity 클래스의 데이터 테이블에 추가

 

위와 같이 Type이 1로 설정된 EventItem Item의 데이터 테이블에 추가된 것을 확인할 수 있습니다.

 

3) Table Splitting

3 - 1) DataModel 클래스

public class ItemDetail
{ 
    public int ItemDetailId { get; set; }
    public string Description { get; set; }
}

[Table("Item")]
public class Item
{
    // Table Splitting 사용예시
    public ItemDetail? Detail { get; set; }

   ...
}

 

Item 데이터 테이블에 추가할 엔티티 클래스인 ItemDetail을 위와 같이 생성하였습니다.

 

3 - 2) AppDBContext 클래스

...

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    ...

    // Table Splitting 사용예시
    modelBuilder.Entity<Item>()
        .HasOne(i => i.Detail)
        .WithOne()
        .HasForeignKey<ItemDetail>(i => i.ItemDetailId);

    modelBuilder.Entity<Item>().ToTable("Item");
    modelBuilder.Entity<ItemDetail>().ToTable("Item");
}

 

OnModelCreating 함수의 로직을 위와 같이 수정하였습니다.

ItemDetail을 Item 테이블에 추가하고 외래키를 ItemDetaulId로 설정합니다.

 

3 - 3) DBCommands 클래스

public static void CreateTestData(AppDBContext db)
{
    ...

    // Splitting Table 예시
    items[2].Detail = new ItemDetail()
    {
        Description = "This is good item"
    };

    ...

    db.SaveChanges();
}

 

CreateTestData 함수를 위와 같이 수정하였습니다.

Item 테이블의 세 번째 아이템ItemDetail 데이터를 추가하고 설정하였습니다.

 

3 - 4) 실행결과

Table Splitting 방식으로 다수의 Entity 클래스를 Item 테이블에 매핑

 

세 번째 아이템에 대한 ItemDetail의 Description이 위와 같이 설정된 것을 확인할 수 있습니다.

728x90
반응형