1

부모 개체에 자식 개체를 추가하는 것이 매우 느려지는 문제가 있습니다. 수만 개의 자식 개체 (이 경우 33k 개의 레코드)가 있지만 그 중 아무 것도 해당 부모 개체의 자식이 아닙니다.엔티티 프레임 워크 속도가 느려질 때 느려짐

나는 부모에게 첫 번째 자식을 추가가 완료 될 때까지 1 분 이상 걸리는 경우 :

public class ParentEntity // POCO generated by EF TT4 templates 
{ 
    public virtual int Id { get; set; } 
    public virtual ICollection<ChildEntity> ChildEntities {} 
} 

public class ChildEntity // POCO generated by EF TT4 templates 
{ 
    public virtual int Id { get; set; } 
    public virtual int ParentEntityId { get; set; } 
    public virtual ParentEntity ParentEntity { get; set; } 
    public virtual Warehouse Warehouse { get; set; } 
    public virtual WarehouseLocation WarehouseLocation { get; set; } 
} 

public class Warehouse { // etc } // another POCO class 
public class WarehouseLocation { // etc } // another POCO class 

// somewhere in a controller action method... 
var parent = _parentEntityService.GetBy(id); 
var child = new ChildEntity{ ParentEntityId = id, 
          WarehouseId = id2, WarehouseLocationId = id3 }; 

// ChildEntities.Add() takes more than one minute to add the 
// first and only child to this parent 
// why would this be so incredibly slow? 

parent.ChildEntities.Add(child); 

EntityFramework의 속도 문제를 찾아 접근하는 가장 좋은 방법은 무엇입니까?

업데이트 : 그것은 단지 현재의 아이 만 그들을로드해야 할 때,

SELECT * FROM ChildEntities where ParentId = id 
SELECT * FROM ChildEntities where WarehouseId = id2 
SELECT * FROM ChildEntities where WarehouseLocation = id3 

는 왜 매일 ChildEntity 이러한로드 않습니다 EFProf이 세 가지 SQL 쿼리를 발행하는 것을 보여줍니다?

편집 2 : @LadislavMrnka에 따라 추가 쿼리는 템플릿의 Fixup 메서드로 인해 발생합니다. 그러나 필자가 그러한 방법을 주석 처리하고 Fixup에 대한 호출을 주석 처리하면 여전히 느립니다. 픽스를 제거하려면이되지 올바른 방법인가 (그것은 나에게 제거 된 것 같습니다) :

public class ChildEntity { 
public virtual Warehouse Warehouse 
{ 
    get { return _warehouse; } 
    set 
    { 
     if (!ReferenceEquals(_warehouse, value)) 
     { 
      var previousValue = _warehouse; 
      _warehouse = value; 
      //FixupWarehouse(previousValue); // commented out 
     } 
    } 
} 
+0

이렇게 변경해보십시오. 'var parent = _parentEntityService.GetBy (id); var child = 새 ChildEntity {Foo = "", Bar = "", 부모 = 부모}; _ entityService.Save (자식)' –

+0

그리고 엔티티의 내부를 보려면 EF Profiler (http://efprof.com/)를 사용하십시오. 뼈대. –

+0

'부모 '엔티티에 많은 수의 ChildEntities가 있습니까? – Eranga

답변

0

이 엄청나게 나를 도와 :

context.Configuration.AutoDetectChangesEnabled = false; 

나는이 당신을 위해가는 경우 확실하지 않다 네가 정확하게 질문을 이해한다면, 너는 단지 Add 일 때 느리다.

그래도 개체를 삽입 할 수는 있지만 EF는 개체 계층을 탐색하는 데 훨씬 적은 노력을 기울입니다. 나는 이것이 엔티티를 업데이트 할 때 문제가 있다고 생각하지만 확실하지는 않습니다.

두 번째 방법 (당신이 DbContext를 사용하는 가정)입니다 :

using (var dbCtx = new MyDataContext()) 
{ 
    var ctx = ((IObjectContextAdapter)dbCtx).ObjectContext; 

    var customers = ctx.CreateObjectSet<Customer>(); 

    customers.AddObject(customer); 
} 

ObjectContext 변경에 관하여 다른 내부적으로 일을 처리하기 때문에. 지금 당장 그 자료를 찾을 수 없지만, 나중에 찾으려고 노력할 것입니다.

var child = new ChildEntity 
       { 
        Foo = "", 
        Bar = "", 
        ParentEntityId = id, 
        WarehouseId = 1, 
        WarehouseLocationId = 1 
       }; 

parent.ChildEntities.Add(child); 

이 IMHO은 모든 POCO 템플릿에 의해 생성 된 코드에 숨겨진 픽스 컬렉션에 관한 것입니다 :

5

이 당신의 문제입니다. Fixup + lazy loading = 성능 문제. Fixup은 모델의 모든 것을 동기화하여 만듭니다. 즉, 네비게이션 속성 또는 FK 속성의 한면을 설정하면 관계의 반대쪽에있는 탐색 속성이 변경 사항을 반영하는지 확인하려고합니다. 문제는 탐색 속성이로드되지 않으면 지연로드를 트리거한다는 것입니다. 귀하의 경우는웨어 하우스를 설정하면 첫 ChildEntity에서 탐색 속성을 고정하고 그 이후 Warehouse 인스턴스에서 탐색 속성을 오류 복구 할 수 있지만 자식 엔티티의 컬렉션

SELECT * FROM ChildEntities where WarehouseId = some id 

같은 원인 => 게으른 로딩을로드되지 않았습니다 시도하고있다처럼 보인다 WarehouseLocation의 경우 발생했습니다. 첫 번째 쿼리는 부모 엔터티에로드되지 않은 컬렉션에 자식을 추가 한 결과입니다.

해결 방법은 템플릿을 수정하고 모든 픽스 업을 제거하는 것입니다 (예 : EFv4 용 DbContext POCO 템플릿).좋아

public class DisableLazyLoadingScope : IDisposable 
{ 
    private readonly ObjectContext context; 

    public DisableLazyLoadingScope(ObjectContext context) 
    { 
     this.context = context; 
     context.ContextOptions.LazyLoadingEnabled = false; 
    } 

    public void Dispose() 
    { 
     context.ContextOptions.LazyLoadingEnabled = true; 
    } 
} 

그리고 그것을 사용 : 1+ 이상 픽스 업 사용) 또는 호출하여이 작업 지연로드를 해제하지 않습니다

context.ContextOptions.LazyLoadingEnabled = false; 

// Your insert logic here 

context.ContextOptions.LazyLoadingEnalbed = true; 

심지어 같은 정의는 IDisposable의 코드를 포장 할 수 있습니다 :

using (new DisableLazyLoadingScope(context) 
{ 
    // Your insert logic here 
} 
+0

아하, 이해해. 고마워. 픽스 업이 우리에게주는 혜택은 무엇입니까? 나는 그것이 TT4 템플릿에 있었기 때문에 나는 그것을 가지고 있으며, 그것이 필요하지 않다면 나는 그것을 제거하는 것이 행복 할 것이다. 지금 EF4.1을 사용하고 있지만 템플릿을 처음 추가 할 때 이전 EF 버전을 사용하고있었습니다. –

+0

Fixup은로드 된 데이터를 동기화 상태로 유지합니다. 한 쪽 수정에서'WarehouseId'를 설정하면'Warehouse' 네비게이션 프로퍼티에 올바른'Warehouse' 엔티티가 있고'Warehouse' 엔티티가 관련 엔티티의 콜렉션에 여러분의 아이를 갖도록합니다. 부작용은 지연로드를 사용하는 경우 사용하지 않으려는 경우에도 해당 엔티티를로드한다는 것입니다. –

+0

ChildEntity에서 픽스 업을 제거했지만 여전히 느립니다. 모든 엔티티에서 픽스 업을 제거하려고합니다.나는 4.1 자체 추적 엔터티 템플릿을 보았고 여전히 Fixup (다르게 구현 됨)을 가지고있다 :'var previousValue = _warehouse; _warehouse = value; FixupWarehouse (이전 값); OnNavigationPropertyChanged ("Warehouse"); ' –