运行Linq语句的超时异常

时间:2013-12-23 23:20:46

标签: c# sql linq sql-server-2008 entity-framework

这刚刚开始发生。这个声明已经工作了几个月,现在我只是继续得到下面的超时错误。当我直接在SSMS上执行相同的语句时,它会在一秒钟内返回。该表有44k记录,并且是5列状态为其中之一的索引。

select distinct(state) from [ZipCodeDatabase]

我正在运行以下linq语句

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

当我运行这个linq语句时,我不断收到超时错误并且不知道y因为它之前正常工作。

我包含了Get()函数,它是一个通用的repo函数,但也许我在那里遗漏了一些东西,这导致了延迟。

获取功能:

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):超时已过期。操作完成之前经过的超时时间或服务器没有响应。 ---&GT; System.ComponentModel.Win32Exception(0x80004005):等待操作超时      在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action 1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction)      在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)      在System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean&amp; dataReady)      在System.Data.SqlClient.SqlDataReader.TryCloseInternal(Boolean closeReader)      在System.Data.SqlClient.SqlDataReader.Close()      在System.Data.Common.DbDataReader.Dispose(布尔处理)      在System.Data.Common.DbDataReader.Dispose()      在System.Data.Common.Internal.Materialization.Shaper 1.Finally() at System.Data.Common.Internal.Materialization.Shaper 1.SimpleEnumerator.Dispose()      在System.Collections.Generic.List 1..ctor(IEnumerable 1个集合)      at System.Linq.Enumerable.ToList [TSource](IEnumerable 1 source) at ClientsToProfitsKendoUI.DAL.GenericRepository 1.Get(Expression 1 filter, Func 2 orderBy,String includeProperties)

2 个答案:

答案 0 :(得分:5)

您的get方法始终调用ToList,这会在该点实现查询。这意味着它会在进行任何过滤之前从数据库中获取所有44k记录。

在实际选择任何数据之前,您还要按州进行排序,这对订购任意数据是无用的。

使用Get方法,移除ToList来电。首先选择State,然后调用Distinct然后订购,优化您的查询。这允许数据库以最佳方式完成任务。

如果您需要完全具体化列表,请在最后调用ToList。但在此之前,请继续使用查询返回的IQueryable。这样你就可以让Entity Framework尽可能地卸载到数据库中。

答案 1 :(得分:2)

您只是为了选择不同的状态而实现数据库中的每一行。让数据库为你做繁重的工作,只需返回状态而不是实现一切,然后让.Net这样做。

将其添加到ZipCodeRepository

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

请注意,导致实现(以及大量开销)的原因是ToList()

通常,将集合保留为IQueryable,直到您真正准备好使用结果为止。实际枚举集合EF的那一刻,无论如何都会实际执行查询。

或者,如果您删除ToList()来电,并将Get功能的返回类型更改为IQueryable<TEntity>,这也应解决问题。