developer tip

엔티티 프레임 워크 4.1 및 MVC3에서 동적 프록시를 활성화하거나 비활성화해야합니까?

optionbox 2020. 11. 8. 09:47
반응형

엔티티 프레임 워크 4.1 및 MVC3에서 동적 프록시를 활성화하거나 비활성화해야합니까?


누군가가이 결정을 내리는 데 도움이 될 몇 가지 조언을 제공하거나 블로그 / 기사를 지적 할 수 있습니까? 프록시는 나에게 매우 이질적인 것처럼 보이며 사용하는 것이 주저합니다. 내 모델에서 가상 속성을 사용하여 지연로드를 제어하는 ​​기능이 마음에 들지만, 이것이 내가 볼 수있는 모든 이점입니다. 내 애플리케이션은 단순한 MVC 웹 애플리케이션이며 엔티티가 변경된 상태를 경험할 때 컨텍스트에 후크를 연결할 필요가 없습니다.

어쨌든, 여기에 내 장단점 목록이 매우 제한되어 있습니다. 내가 이것 중 하나를 가지고 있지 않은지 알려주십시오.

장점

  • '저장'또는 '업데이트'에서 '변경 사항 적용'으로 원활하게 처리됩니다.
  • Lazy-Loading 구성은 매우 쉽습니다.

단점

  • 내 엔티티에 대해 이전에 프록시를 사용한 적이 없었습니다. 이것은 나 자신과 동료 팀원에게 불편 해 보이는 접근 방식의 변화입니다.
  • 디버그하기 어색합니다.
  • 직렬화 / 직렬화 해제하려면 추가 코드가 필요합니다.
  • '저장'또는 '업데이트'에서 프록시는 컨텍스트에서 검색된 객체와 동일해야합니다.

EF에서 동적 프록시에 대해 이야기하는 경우 구별 할 두 가지 유형이 있습니다.

  • 지연 로딩을위한 프록시
  • 변경 내용 추적을위한 프록시

일반적으로 변경 추적 프록시는 지연로드에 대한 프록시 역할을 할 수도 있습니다. 그 반대는 사실이 아닙니다. 이는 변경 추적 프록시에 대한 요구 사항이 더 높기 때문이며, 특히 모든 속성 (스칼라 속성 포함)이 virtual. 지연로드의 경우 탐색 속성이 virtual.

변경 추적 프록시가 항상 지연로드를 활용할 수 있다는 사실이 DbContext에 다음 구성 플래그가있는 주된 이유입니다.

DbContext.Configuration.LazyLoadingEnabled

이 플래그는 기본적으로 true입니다. false프록시가 생성 된 경우에도 지연로드 비활성화 하도록 설정합니다 . 이는 변경 추적 프록시로 작업하지만 지연로드에도 해당 프록시를 사용하지 않으려는 경우 특히 중요합니다.

옵션 ...

DbContext.Configuration.ProxyCreationEnabled

... 프록시 생성을 완전히 비활성화합니다. 변경 사항 추적 및 지연로드도 가능합니다.

두 플래그는 엔터티 클래스가 변경 추적 또는 지연로드 프록시를 만들기위한 요구 사항을 충족하는 경우에만 의미가 있습니다.

이제 동적 지연로드 프록시의 목적을 알았습니다. 그렇다면 왜 동적 변경 추적 프록시를 사용해야합니까?

실제로 내가 아는 유일한 이유는 성능 입니다. 그러나 이것은 매우 강력한 이유입니다. 스냅 샷 기반 변경 추적을 프록시 기반 변경 추적과 비교하면 성능 차이가 큽니다. 측정 값에서 50에서 100까지의 계수는 현실적입니다 (스냅 샷 기반 변경 추적을 사용하는 10000 개의 항목에 대해 약 1 시간이 필요한 방법에서 가져옴) 및 30-60 초 변경 내용 추적 프록시를 활성화하기 위해 모든 속성을 가상으로 만든 후). 이는 많은 (예 : 1000 개 이상의) 엔티티를 처리하고 변경하는 애플리케이션이있는 경우 중요한 요소가됩니다. 웹 요청의 단일 엔터티에 대해 만들기 / 변경 / 삭제 작업 만있을 수있는 웹 응용 프로그램에서이 차이는 그다지 중요하지 않습니다.

지연로드 프록시로 작업하지 않으려는 경우 거의 모든 상황에서 eager 또는 명시 적로드를 활용하여 동일한 목표를 달성 할 수 있습니다. 프록시 기반 지연로드 또는 비 프록시 기반 명시 적로드의 성능은 동일합니다. 기본적으로 탐색 속성이로드 될 때 동일한 쿼리가 발생하기 때문입니다. 첫 번째 경우 프록시가 쿼리를 수행하고 두 번째 경우에는 손으로 작성한 코드입니다. 따라서 많은 손실없이 지연로드 프록시없이 살 수 있습니다.

그러나 많은 엔터티를 처리하기 위해 합리적인 성능을 원하는 경우 변경 추적 프록시에 대한 대안이 없습니다 EntityObject. EF 4.0에서 파생 엔터티를 사용 DbContext하거나 Entity Framework를 전혀 사용하지 않는 것 외에는 EF 4.1의 옵션이 아닙니다. .

편집 (2012 년 5 월)

그동안 변경 추적 프록시 가 스냅 샷 기반 추적에 비해 성능이 더 빠르거나 더 나쁘지 않은 상황이 있다는 것을 알게 되었습니다.

변경 추적 프록시를 사용할 때 이러한 복잡성으로 인해 선호되는 방법은 기본적으로 스냅 샷 기반 변경 추적을 사용하고 고성능이 필요하고 스냅 샷 기반보다 빠른 경우에만 프록시를 신중하게 (일부 테스트를 수행 한 후) 사용하는 것입니다. 변경 추적.


Entity Framework 5를 사용하는 모든 사용자는 성능 고려 사항 문서 를 확인 하십시오. Sections 5 NoTracking Queries그리고 8 Loading Related Entities이벤트는 정보를 당신은 정보통 결정을 내릴 필요가있다. 건배.


프록시를 사용하지 않는 것이 좋습니다. 동적 프록시 생성은 런타임 유형 검사에 의존하는 구성 요소를 중단하거나 복잡하게 만듭니다.

예를 들어 Automapper는 엔티티가 자동 매핑을 구성 할 때 전달한 유형이 아닌 런타임 중에 동적으로 생성 된 프록시 유형을 가지므로 런타임 중에 유형 불일치 / 예기치 않은 유형 오류를 발생시킵니다.


동적 프록시에는 몇 가지 멋진 기능이 있지만 실제로는 이상하고 모호한 버그를 많이 만들 수 있습니다.

예를 들어, 내 클래스 중 하나에서 엔티티의 개인 변수를 유지하고 (배치 프로세스를 구현하고 있었음) 수백만 개의 레코드를 반복하여 처리하고 배치로 삽입하고 n 레코드마다 데이터 컨텍스트를 재생성했습니다. 메모리를 청소하십시오. 개인 변수를 사용한 적이 없지만 EF는 참조 ID 만 설정 했음에도 불구하고 새 개체 (탐색 속성을 통한 참조가 있음)에 연결했습니다.

이로 인해 프로세스가 실행되는 동안 모든 개체가 메모리에 남아 있습니다. 프로세스가 예상대로 작동하고 메모리와 성능이 정상 수준으로 돌아가려면 AsNoTracking을 사용하고 프록시를 비활성화해야했습니다. 프록시는 또한 프록시를 생성 한 컨텍스트를 참조하며 이는 메모리에 엔티티의 거대한 그래프를 유지할 수 있으며 디버그하는 것은 거의 불가능합니다.

따라서 프록시를 전역 적으로 비활성화하고 작고 포함 된 코드 조각으로 활성화해야한다고 생각합니다. 대규모 팀이 코딩하는 경우 이러한 문제를 특히 디버깅하는 것은 매우 위험하고 불가능합니다.

변경 내용 추적은 훌륭하며 일부 장소에서의 사용을 정당화 할 수 있습니다. 지연로드는 수행중인 작업을 알지 못하는 경우 성능 및 직렬화에 큰 문제가 될 수 있습니다. 항상 열성적이거나 명시적인 로딩을 선호합니다.


Automapper 4.2.1을 사용하십시오. 새 버전에는 DynamicMap이 없습니다.

var parents = parentsRepo.GetAll().ToList();
Mapper.CreateMap<Parent,ParentDto>();
var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);

참고 URL : https://stackoverflow.com/questions/7111109/should-i-enable-or-disable-dynamic-proxies-with-entity-framework-4-1-and-mvc3

반응형