Entity와 DB Table 간 연동하는 다양한 방법들에 대해 알아보자
Entity class 하나를 통으로 Read/Write하는 것은 부담이 되기 때문에 이전 시간에 Select Loading, DTO를 활용했었다. 하지만 이 외에도 기본적인 방법들이 몇가지 존재한다.
일반 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을 설정하는 여러가지 방법이 있다.
protected override void OnModelCreating(ModelBuilder builder)
{
// 이 타입을 별도의 테이블로 분리해서 관리하는게 아니라 자신의 테이블에 포함하고 싶을 경우
builder.Entity<Item>()
.OwnsOne(i => i.Option); // Option_Str, Option_Dex, Option_Hp 열이 추가됨
}
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");
상속 관계의 여러 class <-> 하나의 테이블에 매핑
public class EventItem : Item // 기간제 아이템
{
public DateTime DestroyDate { get; set; }
}
public DbSet<Item> Items { get; set; }
public DbSet<EventItem> EventItems { get; set; }
위와 같이 코딩하면 EventItem 테이블이 따로 생성되지 않고, DestroyDate 열이 Item 테이블에 하나 추가된 것을 볼 수 있다. 행마다 Item인지 EventItem인지 구분하는 것은 Discriminator 열이 따로 추가되어서 Item이면 Item으로 세팅되어 있는 것을 볼 수 있다.
ItemType enum을 Discriminator로 사용할 수 있다.
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; }
}
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);
}
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);
다수의 Entity class <-> 하나의 테이블에 매핑
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; }