Relationship Config

Eunho Bae·2022년 7월 1일
0

기본 용어 복습

  • principal key = 주키 또는 Unique한 Alternate key
  • required relationship : Non-null
  • optional relationship : nullable

Convention을 이용한 외래키 설정

    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번째 방식으로 외래키 이름을 설정했다.

<PrincipalKeyName>

PlayerId

<Class><PrincipalKeyName>

PlayerPlayerId

OwnerPlayerId 또는 OwnerId

외래키와 Nullable (복습)

Required Relationship (non-null)

무조건 null이 아닌 principal 데이터를 가지고 있어야 하기 때문에 삭제할 때 OnDelete의 인자를 Cascade 모드로 호출하기 때문에 Principal 데이터를 삭제하면 Dependent 데이터도 삭제된다.

Optional Relationship

삭제할 때 OnDelete 인자를 ClientSetNull 모드로 호출하기 때문에 Principal 삭제할 때 Dependent tracking 중이면 외래키를 NULL로 세팅한다.
그러나 만약 Principal 삭제할 때 Dependent tracking 하고 있지 않으면 Exception 발생!!

Convention 방식으로 못하는 것들

  • 복합 외래키
  • 아래와 같이 다수의 Navigational Property가 같은 클래스를 참조할 때 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; }
        ...
    }
  • DB나 삭제 관련 커스터마이징이 필요할 때. 즉 위에서 일련의 삭제 규칙들을 바꾸고 싶을 때

Data Annotation으로 Relationship 설정

외래키

두 가지 방법이 있다.

        [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")]

InverseProperty

다수의 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; }
       ...
   }

Fluent API로 추가

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> 추가
        }
profile
개인 공부 정리

0개의 댓글