2013-12-23 3 views
3

이것은 막 시작되었습니다. 이 진술은 몇 달 동안 작동했지만 이제는 아래의 시간 초과 오류가 계속 발생합니다. SSMS에서 똑같은 성명을 직접 실행하면 잠시 후에 다시 돌아옵니다. 테이블은 44k 개의 레코드를 가지며 5 개의 컬럼 상태에 대한 인덱스 중 하나입니다. 내가 계속 시간 초과 오류가 발생하고이 LINQ 문을 실행하고 이전에 제대로 작동 된 이후 아무 생각 y를이없는 경우Linq 문 실행 시간 초과 예외

select distinct(state) from [ZipCodeDatabase] 

나는 다음과 같은 LINQ 문

states = ZipCodeRepository.Get(orderBy: z => z.OrderBy(o => o.State)).Select(z => z.State).Distinct().ToList(); 

을 실행하고 있습니다.

일반적인 repo 기능인 Get() 기능이 포함되어 있지만 지연을 유발하는 내용이 누락되었을 수 있습니다.

가져 오기 기능 :

public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null, 
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
string includeProperties = "") //params Expression<Func<TEntity, object>>[] includes 
{ 
    IQueryable<TEntity> query = dbSet; 
    if (filter != null) 
    { 
     query = query.Where(filter); 
    } 
    foreach (var includeProperty in includeProperties.Split 
     (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
    { 
     query = query.Include(includeProperty); 
    } 

    if (orderBy != null) 
    { 
     return orderBy(query).ToList(); 
    } 
    else 
    { 
     return query.ToList(); 
    } 
} 

시간 초과 오류 :

System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlDataReader.TryCloseInternal(Boolean closeReader) at System.Data.SqlClient.SqlDataReader.Close() at System.Data.Common.DbDataReader.Dispose(Boolean disposing) at System.Data.Common.DbDataReader.Dispose() at System.Data.Common.Internal.Materialization.Shaper 1.Finally() at System.Data.Common.Internal.Materialization.Shaper 1.SimpleEnumerator.Dispose() at System.Collections.Generic.List 1..ctor(IEnumerable 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable 1 source) at ClientsToProfitsKendoUI.DAL.GenericRepository 1.Get(Expression 1 filter, Func 2 orderBy, String includeProperties)

+2

이것은 일반적으로 SQL에서 발생하는 유형 변환을 의미합니다. 나는 이것이'datetime'이'nvarchar'로 변환 될 때 일어나는 것을 보았습니다. 쿼리 창에서 1ms 미만의 시간은 코드를 통해 전송할 때 시간 초과됩니다. 확인하는 유일한 방법은 쿼리 프로파일 러를 사용하여 무슨 일이 일어나는지 확인하는 것입니다. –

+3

주를 얻으려고 모든 44K 기록을 구체화하고 있습니까? – McAden

답변

2

당신은 데이터베이스에있는 모든 행을 구체화하고는 별개의 상태를 선택합니다. 데이터베이스가 당신을 위해 무거운 짐을 싣고 모든 것을 실현시키고 닷넷을 사용하는 것보다는 단순히 주정부를 반환하게하십시오.

은 ZipCodeRepository에 무엇을 구체화 (오버 헤드의 톤)을 일으키는 것은 ToList() 것을

public IEnumerable<string> GetStates() 
{ 
    return dbSet.OrderBy(e => e.State).Select(e => e.State).Distinct(); 
} 

참고이를 추가합니다.

일반적으로 결과를 사용할 준비가 될 때까지 컬렉션을 IQueryable로 유지하십시오. 실제로 컬렉션을 열거하면 EF가 실제로 쿼리를 수행합니다.

ToList() 호출을 제거하고 함수의 반환 형식을 IQueryable<TEntity>으로 변경하면이 문제도 해결됩니다.

5

get 메서드는 항상 해당 시점에 쿼리를 구체화하는 ToList을 호출합니다. 필터링을 수행하기 전에 데이터베이스에서 모든 44k 레코드를 가져옵니다.

실제로 임의의 데이터를 선택하기 전에 상태별로 정렬을 수행하기 때문에 임의의 데이터를 정렬하는 데 쓸모가 없습니다.

Get 메서드에서 ToList 호출을 제거하십시오. 먼저 State을 선택한 다음 Distinct을 호출하고 주문하면 쿼리가 최적화됩니다. 이것은 데이터베이스가 최선을 다할 수있게합니다.

목록이 완전히 구체화되어야하는 경우 끝에 ToList으로 전화하십시오. 그러나 그 전까지는 쿼리가 반환하는 IQueryable을 계속 사용하십시오. 그렇게하면 Entity Framework에서 가능한 한 데이터베이스를 오프로드 할 수 있습니다.

+1

덕분에 나는 또한 이것을 수행하고 Get 메서드에서 모든 to 목록을 제거했습니다. – ChampChris