简体   繁体   English

运行Linq语句的超时异常

[英]Timeout exception running Linq Statement

This just started happening. 这才刚刚开始发生。 This statement was working for months, now I just keep getting the timeout error below. 这个声明已经工作了几个月,现在我只是继续得到下面的超时错误。 when I execute the same statement directly on the SSMS it comes back in a second. 当我直接在SSMS上执行相同的语句时,它会在一秒钟内返回。 the table has 44k records and is index on 5 columns state being one of them. 该表有44k记录,并且是5列状态的索引,其中一列是其中之一。

select distinct(state) from [ZipCodeDatabase]

I am running the following linq statement 我正在运行以下linq语句

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

When I run this linq statement I am continually getting a timeout error and have no idea y since it was working correctly before. 当我运行这个linq语句时,我不断收到超时错误并且不知道y因为它之前正常工作。

I included the Get() function which is a generic repo function, but maybe I am missing something there, that is causing the delay. 我包含了Get()函数,它是一个通用的repo函数,但也许我在那里遗漏了一些东西,这导致了延迟。

Get Function: 获取功能:

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();
    }
}

The timeout error: 超时错误:

System.Data.SqlClient.SqlException (0x80131904): Timeout expired. System.Data.SqlClient.SqlException(0x80131904):超时已过期。 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 ---> System.ComponentModel.Win32Exception(0x80004005):在System.Data.SqlClient.SqlInternalConnection.OnError处的System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action 1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action等待操作超时1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)中的1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action 1 wrapCloseInAction) 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 at System.Data.Common.Internal.Materialization.Shaper的System.Data.Common.DbDataReader.Dispose 1.Finally() 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) 1.Finally() at System.Data.Common.Internal.Materialization.Shaper ()在System.Collections.Generic.List 1..ctor(IEnumerable 1 collection)System.Linq.Enumerable.ToList [TSource](IEnumerable 1 source) at ClientsToProfitsKendoUI.DAL.GenericRepository (表达式1 filter, Func 2 orderBy,String includeProperties)

Your get method always calls ToList , which materializes the query at that point. 您的get方法始终调用ToList ,该列表在此时实现查询。 Meaning that it will grab all 44k records from the database before doing any filtering. 这意味着它会在进行任何过滤之前从数据库中获取所有44k记录。

You're also doing the ordering by state before actually selecting any data, which is a useless exercise in ordering arbitrary data. 在实际选择任何数据之前,您还要按状态进行排序,这对于排序任意数据是一种无用的练习。

From your Get method, remove the ToList calls. Get方法中,删除ToList调用。 And optimize your query by first selecting the State , then calling Distinct and then ordering. 并通过首先选择State ,然后调用Distinct然后排序来优化您的查询。 This allows the database to do its thing optimally. 这允许数据库以最佳方式完成任务。

If you need the list fully materialized, call ToList at the very end. 如果您需要完全具体化的列表,请在最后调用ToList But until that, keep using the IQueryable which your query returns. 但在此之前,请继续使用查询返回的IQueryable That way you can let Entity Framework offload as much as possible to the database. 这样,您可以让Entity Framework尽可能多地卸载到数据库中。

You're materializing every row in the database just to select distinct states. 您只是为了选择不同的状态而实现数据库中的每一行。 Let the database do the heavy lifting for you and simply return the states rather than materializing everything and then having .Net do it. 让数据库为您完成繁重的工作,只需返回状态而不是实现所有内容,然后让.Net执行此操作。

Add this to your ZipCodeRepository 将其添加到ZipCodeRepository中

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

Note that what's causing the materialization (and a ton of overhead) is the ToList() . 请注意,导致实现(以及大量开销)的原因是ToList()

In general, keep the collection as an IQueryable until you're actually ready to to use the results. 通常,将集合保留为IQueryable,直到您真正准备好使用结果。 The moment you actually enumerate the collection EF will actually perform the query for you anyway. 实际枚举集合EF的那一刻,无论如何都会实际执行查询。

Alternatively, if you remove the ToList() calls and change the return type of the Get function to be IQueryable<TEntity> that should also resolve the issue. 或者,如果删除ToList()调用并将Get函数的返回类型更改为IQueryable<TEntity> ,它也应解决该问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM