- 개요
생성한 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의 PK가 ItemOption의 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에 따라 NormalItem과 EventItem으로 구분합니다.
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) 실행결과

위와 같이 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) 실행결과

세 번째 아이템에 대한 ItemDetail의 Description이 위와 같이 설정된 것을 확인할 수 있습니다.
'대형 프로젝트 - C# + 유니티로 만드는 MMORPG 게임 개발 > (5) EF Core' 카테고리의 다른 글
| User Defined Function(UDF) (0) | 2025.08.25 |
|---|---|
| Backing Field + Relationship (0) | 2025.08.25 |
| Shadow Property & Backing Field (0) | 2025.08.19 |
| Relationship Configuration (0) | 2025.08.18 |
| Configuration (0) | 2025.08.18 |