public class Item
{
public bool SoftDeleted { get; set; }
public int ItemId { get; set; }
public int TemplateId { get; set; }
public DateTime CreateDate { get; set; }
public int? OwnerId { get; set; }
public Player Owner { get; set; }
}
Item entity 클래스에서 외래키의 이름을 설정하는 방식에는 3가지가 있다.
강의에서는 3번째 방식으로 외래키 이름을 설정했다.
PlayerId
PlayerPlayerId
OwnerPlayerId 또는 OwnerId
무조건 null이 아닌 principal 데이터를 가지고 있어야 하기 때문에 삭제할 때 OnDelete의 인자를 Cascade 모드로 호출하기 때문에 Principal 데이터를 삭제하면 Dependent 데이터도 삭제된다.
삭제할 때 OnDelete 인자를 ClientSetNull 모드로 호출하기 때문에 Principal 삭제할 때 Dependent tracking 중이면 외래키를 NULL로 세팅한다.
그러나 만약 Principal 삭제할 때 Dependent tracking 하고 있지 않으면 Exception 발생!!
public class Item
{
...
public int? OwnerId { get; set; }
public Player Owner { get; set; }
public int? CreatorId { get; set; }
public Player Creator { get; set; } // 나를 최초로 만든 플레이어
}
public class Player
{
...
public Item Item { get; set; }
public ICollection<Item> CreatedItems { get; set; }
...
}
두 가지 방법이 있다.
[ForeignKey("Owner")]
public int? OwnerId { get; set; }
public Player Owner { get; set; }
또는
public int? OwnerId { get; set; }
[ForeignKey("OwnerId")]
public Player Owner { get; set; }
만약 복합키를 외래키로 설정하고 싶다면 [ForeignKey("ItemId, TemplateId")]
다수의 Navigational Property가 같은 클래스를 참조할 때 누구와 연동되야 하는지를 힌트를 줄 수 있다.
public class Item
{
...
public int OwnerId { get; set; }
//[InverseProperty("Item")]
public Player Owner { get; set; }
public int? CreatorId { get; set; }
public Player Creator { get; set; } // 나를 최초로 만든 플레이어
}
public class Player
{
...
[InverseProperty("Owner")]
public Item Item { get; set; }
[InverseProperty("Creator")]
public ICollection<Item> CreatedItems { get; set; }
...
}
Data Annotation 보다 우선순위가 높아서 덮어쓴다.
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Player>()
.HasMany(p => p.CreatedItems)
.WithOne(i => i.Creator)
.HasForeignKey(i => i.CreatorId); // 1:m 관계에서는 m인 쪽에 외래키
builder.Entity<Player>()
.HasOne(p => p.Item)
.WithOne(i => i.Owner)
.HasForeignKey<Item>(i => i.OwnerId);
// 외래키를 Item쪽에도 설정할 수 있고 플레이어 쪽에다 설정할 수 있기 때문에 찾지 못함.
// Item 쪽에다 넣어줬기 때문에 <Item> 추가
}