2013-05-02 4 views
2

DbSet.Find() 호출에서 끔찍한 성능을 얻고 있습니다. 내 코드는 다음과 같습니다단순 DbSet <TEntity>.Find() Forex Taking 호출

public class Area 
{ 
    [Key] 
    public string Id { get; protected set; } 

    // ... 
} 

public class MyContext : DbContext 
{ 
    //... 
    public DbSet<Area> Areas { get; set; } 
    //... 
} 

// This is the call that takes so long 
Area area = context.Areas.Find(id);  

내가이, 엔티티 세트를 통해 검색 등 변경 내용 추적을 확인해야하고 데이터베이스에 대한 호출을 트리거 할 것을 이해합니다. 문제는 간단한 context.Areas.SingleOrDefault(x => x.Id == id) 호출보다 더 긴 시간 동안 명령을 받는다는 것입니다. 내가 합리적이라고 생각하는 것보다 훨씬 더. 또 다른 질문에 대한 팁에 따라, 나는 또한 일시적으로 성공하지 않고 변경 내용 추적을 해제 시도 (그것이 어떤 효과를 갖고있는 표시되지 않습니다) :

try 
{ 
    context.Configuration.AutoDetectChangesEnabled = false; 
    return context.Areas.Find(id); 
} 
finally 
{ 
    context.Configuration.AutoDetectChangesEnabled = true; 
} 

시도하고이 하단에 도착하기 위해, 나는 해고 내 프로파일 러. 이것은 내가 찾은 것입니다 : 그것은 실행 계획을 준비하고 모든 시간을내어 것처럼

trace

것 같습니다. 그러나 이것이 .Find() 호출 중에 오랜 시간이 걸리고 명시적인 .SingleOrDefault 호출이 아닌 이유는 무엇입니까? (호출 스택의 맨 위까지 실제로는 SingleOrDefault 호출을 준비 중입니다). .Find() 메서드가 실제로 컴파일하려고하는 쿼리를 볼 방법이 있습니까?

+0

해당 지역 클래스의 전체 코드는 무엇입니까? 티는 다른 클래스에서 상속 받았습니까? – jure

+0

@jure - 거의 없습니다. 분명히 몇 가지 다른 속성과 몇 가지 방법이 있지만 대부분의 경우 매우 간단한 엔티티 클래스입니다. – daveaglick

+0

표시된 사진은 검색어의 6 %만을 차지합니다 (나는 6 %의 합계가 100을 넘는 것으로 가정합니다). Area는 다른 많은 엔티티에 대한 참조를 가지고 있습니까? 지연로드가 비활성화되어 있으며 따라서 모든 연결을로드합니까? 문제는 귀하의 작업이 * 관련 그래프를로드하는 것일 수 있습니다. – qujck

답변

1

왜 이렇게 오래 걸리는지 정확히 알 수 없었습니다. 생성 된 쿼리는 합리적인 것처럼 보입니다 (단지 SELECT). 꽤 복잡한 도메인 모델을 사용하고 있습니다. 위에서 설명한 Area 엔터티가 격리되고 단순하지만 Entity Framework는 뷰를 작성하거나 도메인 모델의 다른 부분을 다루는 쿼리를 생성하려고 시도합니다 (또는 오히려 그것을해서는 안됨).

어쨌든 나는 주위에서 일을 공식화했다.

public Area FindArea(string id) 
{ 
    // First see if the DbSet already has it in the local cache 
    Area area = context.Areas.Local.SingleOrDefault(x => x.Id == id); 

    // Then query the database 
    return area ?? context.Areas.SingleOrDefault(x => x.Id == id); 
} 

이 기술은 쉽게 확장 방법을 사용하여 일반화 될 수있다 : 트릭 수동으로 Find() 호출이 처음에하고 있었다 (생각) 일을하는 것입니다. 이 특정 구현에서는 엔티티가 문자열 Id 열에 ID를 저장하고 다음 인터페이스를 구현한다고 가정합니다. 그러나 일부 조정을 통해 모든 종류의 도메인 모델에 적용 할 수 있습니다.

public interface IEntityWithId 
{ 
    string Id { get; } 
} 

public static object FastFind<TEntity>(this DbSet<TEntity> dbSet, string id) 
    where TEntity : IEntityWithId, class 
{ 
    // First see if the DbSet already has it in the local cache 
    TEntity entity = dbSet.Local.SingleOrDefault(x => x.Id == id); 

    // Then query the database 
    return entity ?? dbSet.SingleOrDefault(x => x.Id == id); 
}  
+0

그런 해결 방법으로 문제가 해결 된 것은 정말 이상합니다. 간단한 예제 모델에서 재생성이 가능하고 http://entityframework.codeplex.com/workitem/list/advanced에서 문제를보고 할 수있는 시간을 찾으십시오. – Slauma

관련 문제