공부/EFCore

[EFCore] 다수의 Navigational Property가 같은 클래스를 참조하는 상황, 어떻게 대처할까

돌멩이수프 2022. 9. 7. 15:39
728x90

 

public class Item
{
	// ... //
    public Player Owner { get; set; }
    public Player Creator { get; set; }
}

 

아이템을 생성한 Player와 아이템을 소유하고 있는 Player를 모두 나타내고 싶을 때는 어떤 방법을 사용해야 할까? 기존에 사용하던 Convention 방식을 사용하면 에러가 발생한다. (OwnerId와 CreatorId 두 개를 추가해주는 방식)

 

 

 

✅ 이때 우리가 사용할 수 있는 게 DataAnnotation 방식이다.

 

public class Item
{
    // ... //
    public int? OwnerId { get; set; }
    [InverseProperty("OwnedItem")]
    public Player Owner { get; set; }

    public int? CreatorId { get; set; }
    [InverseProperty("CreatedItems")]
    public Player Creator { get; set; }
}

public class Player
{ 
    // ... //
    public Item OwnedItem { get; set; }
    public ICollection<Item> CreatedItems { get; set; }
}

 

각각 물고 있고 싶은 프로퍼티를 물고 있으면 된다. Player에 있는 OwnedItem이 [InverseProperty("Owner")]를 물고 있어도 정상 작동한다.

 

 

Fluent API로 만드는 방법도 있다.

 

기존에 만든 DataAnnotation 방식의 주석은 모두 삭제하고, 

 

protected override void OnModelCreating(ModelBuilder builder)
{
	// ... //
    builder.Entity<Player>()
        .HasMany(p => p.CreatedItems)
        .WithOne(i => i.Creator) // 상대쪽
        .HasForeignKey(i => i.CreatorId);

    builder.Entity<Player>()
        .HasOne(p => p.OwnedItem)
        .WithOne(i => i.Owner)
        .HasForeignKey<Item>(i => i.OwnerId);
}

 

AppDbContext에 내용을 추가해준다. 자신과 상대를 연결한뒤 FK로 설정하고 싶은 프로퍼티를 작성하면 다수의 Navigational Property가 같은 클래스를 참조하는 상황도 잘 대처할 수 있다.

728x90