2016-06-20 3 views
0

Entity Framework 7을 사용하여 DB에서 데이터를 검색하는 데 사용되는 LINQ 쿼리입니다. .Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First() 몇 가지가 있습니다. 이 쿼리를 최적화하는 방법이 있습니까? 이를 수행 할 필요가 있습니까? 아니면 EF가 최적화합니까? 절 목록을 필터링 아니라 where 절을 하나의 내부 상태를 넣어 어디 AFAIKEF 최적화 복잡한 LINQ 쿼리가 필요합니까?

var bs = await db.Building.Include(x => x.CollectedMaterial) 
        .Where(x => x.MaterialIDLocked == BuildingDataLockType.LockedByBuildingInfoSource) 
        .Where(x => x.CollectedMaterial.Count > 0) 
        .Where(
         x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats >= firstRepeatsCount) 
        .Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().MaterialID != x.MaterialID) 
        .ToListAsync(); 
+0

모든 답은 나에게 유용합니다, 감사를 병합 할 수 있습니다! – AsValeO

답변

2

여러 사용할 수 없습니다.

편집 : 불필요한 데이터를 얻어서 자체가 메모리 개체를 필터링하지 않는 쿼리의 모든 데이터를 필터링합니다, 어쩌면 : 그래 multiple where clauses을뿐만 아니라

팁 사용하기 좋은 것 같다 불필요한 필드조차도 필요한 필드 만 선택하기 위해 프로젝션 작업을 사용할 수 있습니다.

등, 나는 보통 가독성과 성능 승 당신이 메모리, CPU 샘플링을 가지고 Visual Studio Profiler을 시도 또한, 필요한 것입니다 얼마나 많은 성능 개선을 평가하기 위해 시도해야/B 균형 가고, here 너무 그렇게 말

응답

get 메서드에서 해당 코드를 작성하는 경우 DbSet에서 AsNoTracking 메서드를 사용하면 Entity Framework에서 기본적으로 만드는 추적 개체를 사용하여 해당 개체를 추적하지 않으므로 성능이 향상됩니다.

DbContext 개체의 Database.Log 속성을 사용하여 생성 된 SQL 쿼리를 기록하고 어떤 쿼리가 복잡해 보이는 코드를 변경하면이 방법이 도움이 될 것입니다. 당신은 당신이 context.Database.Log = message => Trace.WriteLine(message);

+0

고마워요, 많은 유용한 것들. IQueryable (Petr의 답)에 대해 여러 개의 .Where()가 괜찮습니다. – AsValeO

+1

그래, 여러 개의 .Where() 절을 사용하는 것이 좋을 것 같습니다. 코드의 가독성을 향상시킬 수 있다고합니다. –

1

당신이 IQueryable 작업을하고 있기 때문에 같은 디버그 또는 추적을 다른 응용 프로그램에 로그인 할 수 있습니다 context.Database.Log = Console.WriteLine;

로 콘솔 응용 프로그램에 로그인 할 수 있습니다

, 당신은 당신만큼 .Where() 조건을 체인 수 여러분이 만들고있는 것은 표현식 트리입니다. 나중에 표현됩니다.

실제로 데이터베이스에서 데이터를 검색하면 (예 : ToList()), EF는 실제로 최적화 된 SQL 쿼리를 만듭니다.

그럼 당신이 할 수있는 최선의 방법은 DB에 대해 SQL 프로파일 러를 실행하고 을 생성하여 EF가 생성 한 쿼리를 확인하는 것입니다.

1

AFAIK, 엔티티는 실제 db 호출이 실현 될 때까지 모든 것을 최적화합니다. 귀하의 경우, 그것은 .ToListAsync에 대한 호출이 이루어질 때입니다.

편집 : this 주석을 보면 모든 검색어를 병합해야합니다. 가능하다면 변수 defition을 사용하는 것을 생각해보십시오. 최적화에 관한

, 모든

.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats >= firstRepeatsCount) 
.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().MaterialID != x.MaterialID) 

.Where(x => { 
    var firstRepeats = x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats; 
    return (firstRepeats.Repeats >= firstRepeatsCount && 
      firstRepeats.MaterialID != x.MaterialID) }) 

(테스트되지 않은,하지만)

+0

불행하게도 이것은'IQueryable'과 함께 문장 본문을 사용할 수 없습니다 "문장 본문이있는 람다 식은 표현식 트리로 변환 될 수 없습니다". – AsValeO

+0

그리고 넌 어디서나 성능을 망칠 수 있기 전에 데이터를 추출해서는 안된다. – torendil