2

MVC 프로젝트에서 Entity Framework Profiler를 사용하여 데이터 액세스를 테스트했으며 여러 페이지에서 훨씬 더 많은 데이터베이스를 만들고 있습니다. N + 1 문제로 인해 필요한 쿼리보다많은 쿼리를 만들지 않고 Entity Framework 탐색 속성 사용 (N + 1 사용 안 함)

여기 내 문제 보여주는 간단한 예입니다 :

var club = this.ActiveClub; // ActiveClub uses code similar to context.Clubs.First() 
var members = club.Members.ToList(); 
return View("MembersWithAddress", members); 

뷰는 회원을 통해 루프를하고 또한 자신의 주소를 표시하는 각 구성원에 navigion 속성을 다음과 같습니다. 각 주소 요청은 추가 db 쿼리를 가져옵니다.

이 문제를 해결하는 한 가지 방법은 필요한 추가 테이블이 있는지 확인하기 위해 포함을 사용하는 것입니다. 그러나, 나는 문맥에 직접적으로 붙어있는 Club의 ObjectSet에 대해서만 이것을 할 수있을 것으로 보인다. 이 경우 ActiveClub 속성은 많은 컨트롤러에서 공유되므로 멤버와 주소 테이블을 항상 쿼리하고 싶지는 않습니다. 내가 좋아하는 것

같은 것을 사용할 수 있도록 :

var members = club.Members.Include("Address").ToList(); 

을하지만, 회원은 EntityCollection이며, 그게에 포함 방법이 없습니다.

Member EntityCollection에로드를 강제하고 EF에 주소로드를 요청하는 방법이 있습니까?

또는 EntityCollection 탐색 속성을 이런 방식으로 엔티티에 사용하고 있습니다. 단지 정말 나쁜 생각입니다. 컨텍스트에서로드 할 때로드 할 항목을 알고 있어야합니다. 당신이 게으른 로딩 프록시와 포항 강판을 사용하는 경우이 사용하려고

var members = club.Members.CreateSourceQuery() 
          .Include("Address") 
          .ToList(); 

:

var members = ((EntityCollection<Club>)club.Members).CreateSourceQuery() 
                .Include("Address") 
                .ToList(); 

분명히 두 번째 버전이 있기 때문에 아주 좋은하지 않습니다 당신의 실체가 EntityObject에서 상속하는 경우

답변

5

이 사용하려고 POCO는 EF에 대한 종속성을 제거하는 데 사용되지만 컬렉션을 EF 클래스로 변환해야합니다. 또 다른 문제점은 쿼리가 두 번 실행된다는 것입니다. 게으른 로딩은 Members에 대해 한 번 트리거하여 속성에 액세스 한 다음 ToList에 전화하면 두 번째 쿼리가 실행됩니다. 이는 쿼리를 실행하기 전에 turning off lazy loading으로 해결할 수 있습니다.

ActiveClub이 공유된다고 말하면 파생 된 컨트롤러에 사용되는 기본 컨트롤러의 속성과 같은 것을 의미한다고 생각합니다. 이 경우 다른 컨트롤러에서 다른 코드를 사용하여 속성을 채울 수 있습니다.

+0

감사합니다. 그것은 훌륭하게 작동합니다. 질의의 수를 줄이기 위해 할 수있는 일이 여전히 많지만, 이것이 가장 큰 타격을 입히는 원인이었습니다. –