ejyoo's 개발 노트

EF Core Context 로 조회 시, 객체에 자동으로 연계되어 조회되는 이유 본문

BackEnd/.Net Core

EF Core Context 로 조회 시, 객체에 자동으로 연계되어 조회되는 이유

ejyoovV 2023. 8. 25. 13:34

자료조사 이유

EF Core DbContext를 조회할 때,

따로 조회했음에도 불구하고 참조관계가 설정되어있다면 자동으로 붙어서 결과가 출력되었다.

 

이 원리가 무엇이고 내부에서 어떤 규칙으로 인해 이러한 결과가 나오게 되었는지 궁금해져서

조사를 통해 현상을 정리하고자 한다.

 


현상에 대한 정의

먼저 현상에 대한 정의는 아래와 같다

1. A, B 테이블이 있다.

2. A는 부모테이블 B는 자식테이블로 B는 A를 참조하고 있다.

var aData = Context.AEntity.Where(x => x.IsValid).ToList();

Context.BEntity.Where(x => x.IsValid).ToList();

이와 같이 DbContext에서 A 테이블과 B 테이블을 따로 조회했을 때 

aData에 B테이블의 데이터가 들어가게 되어있다.


질문1. 왜 A에 B데이터가 포함되는가?

EF Core에서 A, B 모델의 참조관계가 설정되어있을 때, DbContext에 접근하여 각각 조회했음에도 불구하고 최종 결과에 A에 B데이터가 자동으로 포함되는 이유가 뭘까?

 

이 이유는 EF Core 특성과 관련되어 몇가지 이유가 있다.

 

1. 로컬 캐싱 (Local Caching)

DbContext 인스턴스는 로컬 캐시를 유지한다.

A와 B를 같은 DbContext 인스턴스를 사용하여 조회했다면, EF Core는 이미 로드된 엔터티를 재사용한다.

따라서, B를 먼저 조회하고 나중에 A를 조회하면, A에 관련된 B의 인스턴스는 이미 로컬 캐시에 있기 때문에 자동으로 포함될 수 있다.

 

2. 네비게이션 속성의 자동로딩

EF Core 의 CodeFirst 기법으로 모델링을 하였을 때,

객체 참조 관련하여 네비게이션 속성과 네비게이션 속성 객체를 명시적으로 작성하는데,

이때 지연로딩(Lazy Loading) 이나 명시적 로딩(Explicit Loading)을 지원 한다.

여기에서 지연로딩을 사용할 때, A의 네비게이션 속성에 접근하면 연결된 B가 자동으로 로드될 수 있다.

하지만 지연로딩은 프록시와 'virtual' 네비게이션 속성이 설정되어있을때만 발생한다.

그래서 모델링을 할 때

public virtual string Name { get; set; }

이런식으로 virtual 를 작성하게 되면 지연로딩을 사용할 수 있는 조건 중 하나가 완성되는 것이다.

 

3. 트래킹 (Tracking)

EF Core DbContext는 기본적으로 조회된 엔터티를 트래킹한다.

트래킹 상태인 엔터티는 DbContext에 의해 관리되고, 연관된 엔터티와의 관계가 자동으로 해결된다.

https://learn.microsoft.com/ko-kr/ef/core/querying/tracking

 

추적 및 비 추적 쿼리 - EF Core

Entity Framework Core의 추적 및 비 추적 쿼리에 대한 정보

learn.microsoft.com

 

결론적으로 위의 EF Core 특성으로 인하여 자동으로 연계되어 조회되는 것 처럼 보인다는 것이다.


결과

따라서 EF Core Context 로 조회 시, 객체에 자동으로 연계되어 조회되는 이유는

EF Core 특성 중 로컬 캐싱LazyLoading 특성으로 인한 현상으로 볼 수 있다.

단, 이러한 특성이 정확하게 발현되려면 아래의 조건이 따라야 한다.

1) EF Core CodeFirst 기법으로 모델링 시 네비게이션 객체에 virtual 키워드를 사용할 것.

2) Lazy Loading 을 사용하기 위한 설정을 해야 할 것.

3) 쿼리 조회 후 메모리에 올릴 것.

 

위의 조건을 따르게 되면,

앞으로 EF Core Context로 조회할 때, 객체에 자동으로 연계되어 조회되는 것을 볼 수 있을 것이다.

 

 


참고할만한 다른 내용

https://ejyoo.tistory.com/470

 

EF Core DbContext 의 로딩방식

EF Core 에서 DBContext를 사용하여 데이터를 조회할 때, 아래의 경우가 있다. 1) 조인하여 한번에 조회 2) 따로 따로 조회 3) DbContext로 각각 접근하여 조회 위의 방법을 통해서 데이터를 조회하게 되는

ejyoo.tistory.com

https://ejyoo.tistory.com/437

 

명시적 외래키 작성할 때 virtual 타입을 쓰는 이유

EF 의 ORM 을 사용하면서 모델을 설계할 때 FluntAPI 를 사용하여 각 엔티티 모델 간 외래키를 지정하는데, 이때 외래키로서의 식별관계를 가지는 각 모델이 참조할 수 있도록 명시적 외래키 라는 필

ejyoo.tistory.com

https://ejyoo.tistory.com/474

 

[EF Core] 쿼리 실행

EF Core 쿼리를 작성한 뒤 클라이언트로 객체를 뿌렸는데, 객체 안에 데이터가 없어서 왜 없는지 알기 위해 EF Core 쿼리에 대해 조사를 하여 정리하려고 한다. 먼저 EF Core 쿼리를 실행하려면 아래의

ejyoo.tistory.com