2013-04-02 2 views
0

Entity Framework 4.3.1 코드 우선을 사용하고 있습니다.속성 첫 번째 엔터티 프레임 워크가 느린 경우

저는 아주 간단한 표현과 엔티티 모델을 가지고 있습니다.

using (var PMCtx = new PMContext("PMEntities")) 
{   
    var results = 
      PMCtx.Fetch<vwSDHOriginalMW>() 
      .Where(x => x.DT >= StartDate && x.DT < EndDate) 
      .ToList(); 
    return results; 
} 

public class vwSDHOriginalMW : IEntityObject, IPMContext 
{ 
    public int Schedule { get; set; } 
    public DateTime DT { get; set; } 
    public int HE { get; set; } 
    public Decimal OrgMW { get; set; }   
    public Decimal DELIVERMW { get; set; } 
    public string NERCCode { get; set; } 
    public string NERCCodeStatus { get; set; } 
    public int SDHSDHID { get; set; } 
} 

이것은 매회 15 초가 걸렸습니다. 이 모델은 Sql Server 2008 데이터베이스의보기에 매핑됩니다. EF가 보내고있는 쿼리를 출력하고 SSMS에서 실행했으며 몇 초도 걸렸습니다.

왜 이것이 Entity Framework에서 느린 이유가 무엇입니까?

IEntityObject는 마커 인터페이스로 보이기 때문에 원래 프로그래머는이 코드가 제네릭에 입력되는 유일한 코드인지 확인할 수 있습니다. 1 가 가져 오기

편집은이 수행하는 데이터 층에 도착하는 일부 계층 래퍼를 통과 끝 :

private DbSet<TEntity> FetchSet<TEntity>() 
     where TEntity : class, IEntityObject 
{ 
     Type PassedType = typeof(TEntity); 
     if (!CheckedTypes.Any(x => x.FullName == PassedType.FullName)) 
      if (!PassedType.GetInterfaces().Any(x => CtxInterfaces.Contains(x))) 
       throw new ArgumentException("Type passed is not a DbSet type of constructed context."); 
      else 
       CheckedTypes.Add(PassedType); 

     return privateContext.Set<TEntity>(); 
} 

쿼리 EF의 예를 청소

SELECT [Schedule], 
    [DT], 
    [HE], 
    [OrgMW], 
    [DELIVERMW], 
    [NERCCode], 
    [NERCCodeStatus], 
    [SDHSDHID], 
    [ScheduleDeliveryHourHistoryID] 
FROM [vwSDHOriginalMW] 
WHERE ([DT] >= '2/17/2013') AND ([DT] < '2/21/2013') 

편집을 보내고있다 2 데이터베이스의 뷰에는 실제로 엔티티 모델에 속성이있는 것보다 하나 많은 열이있었습니다. 모델에 속성을 추가했습니다.

public class vwSDHOriginalMW : IEntityObject, IPMContext 
{ 
    public int Schedule { get; set; } 
    public DateTime DT { get; set; } 
    public int HE { get; set; } 
    public Decimal OrgMW { get; set; }   
    public Decimal DELIVERMW { get; set; } 
    public string NERCCode { get; set; } 
    public string NERCCodeStatus { get; set; } 
    public int SDHSDHID { get; set; } 
    //missing property 
    public int ScheduleDeliveryHourHistoryID { get; set; } 

} 

어제 속성을 추가 한 후, 그것은 잠시 동안 엄청나게 빨라 사초 대신 15에서 실행하지만 오늘은 다시 천천히, 그리고 아무것도 변경되었습니다.

업데이트 : 나는 조금 더 좁혔습니다. 같은 FetchSet을 사용하여 끝낼 수있는 두 가지 방법이 있습니다. 내가 사용하고있는 IEnumerable 대신 IQueryable을 반환합니다. 이것은 정상적인 것으로 보이며 이후에 필터링하므로 가장 바람직합니다. 그러나 IQueryable을 반환하는 메서드는 15 초가 걸리는 반면 IEnumerable은 1 초 미만입니다. (I는 모두 ToList()를 호출하고) FetchAll는 가져 오기 호출하고 내가 변경하는 경우 대신에 IQueryable

public IQueryable<TEntity> Fetch<TEntity>() where TEntity : class, Common.IEntityObject 
{ 
    return privateContext.Fetch<TEntity>(); 
} 

public IEnumerable<TEntity> FetchAll<TEntity>() where TEntity : class, Common.IEntityObject 
{ 
     return privateContext.FetchAll<TEntity>(); 
} 

의는 IEnumerable을 반환하는 래퍼로 밝혀

IEnumerable<vwSDHOriginalMW> results = 
        PMCtx.Fetch<vwSDHOriginalMW>() 
        .Where(x => x.DT >= StartDate && x.DT < EndDate) 
        .ToList(); 

IEnumerable<vwSDHOriginalMW> results = 
        PMCtx.Fetch<vwSDHOriginalMW>() 
        .ToList() 
        .Where(x => x.DT >= StartDate && x.DT < EndDate); 

빠릅니다. 그러나 이것은 where 절이 데이터베이스에 전달되기를 원하는 것처럼 보이기 때문에 받아 들일 수 없습니다. 이 경우에는 dev 환경에서 뷰는 180 행에 불과하지만 수백만이 될 가능성이 있으므로 필자가 필터링하기 전에 모든 결과를 메모리에 반환하고 싶지는 않습니다.

+0

"IEntityObject"란 무엇입니까? 게으른 로딩이 사용 중지 되었습니까? 생성되는 샘플 SQL은 무엇입니까? 당신은 Fetch method와 어떤 비슷한가요? – AFD

+0

원본 게시물이 업데이트되었습니다. IEntityObject는 빈 마커 인터페이스입니다. 다른 세부 사항은 게시물에 있습니다. – Dodecapus

+0

나는이 부분을 놓쳤다. 예, 게으른로드가 사용 중지 된 것처럼 보입니다. 그것을 켜면 아무런 효과가 없었습니다. 어쨌든보기에는 184 개의 행만 있습니다. – Dodecapus

답변

0

많은 파문과 많은 두통을 겪은 후 뷰에서 클러스터되지 않은 인덱스가없는 테이블을 참조하는 다른 데이터베이스 인스턴스의 뷰를 참조하고 있음을 알았습니다. 이로 인해 실행 계획이 잘못 캐싱되었습니다.

USE [OTHERDATABASE] 
GO 
CREATE NONCLUSTERED INDEX [IX_ScheduleEnergyProfileJoin] 
ON [dbo].[WTXS_ScheduleEnergyProfile] ([SEQSDR]) 
INCLUDE ([SEQSEPI],[StartDate],[EndDate]) 
GO 

그럼 내가 사용하고 볼 수있는 데이터베이스에 대한 실행 계획 캐시를 삭제 : 쿼리가 빠르게 실행

USE [MYDATABASE] 

DBCC FREEPROCCACHE 
DBCC DROPCLEANBUFFERS 

다른 데이터베이스에 인덱스를 추가 한 후. 그래서 EF가 사용하고 있다고 말한 SQL은 아마 데이터베이스에 보내지는 SQL이 아니라는 것이 판명되었습니다. 이야기의 도덕은 실제로 보내질 SQL을 출력하기 위해 다음에 의존하는 대신이 데이터베이스에 대해 프로파일 링 권한을 얻으려면 어떤 일을 했어야했는지입니다.

var sql = ((System.Data.Entity.Infrastructure.DbQuery<vwSDHOriginalMW>)results).ToString(); 
관련 문제