【问题标题】:Timeout exception running Linq Statement运行 Linq 语句超时异常
【发布时间】:2014-01-12 05:05:42
【问题描述】:

这才刚刚开始。这个声明已经工作了几个月,现在我只是不断收到下面的超时错误。当我直接在 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):超时。在操作完成之前超时时间已过或服务器没有响应。 ---> System.ComponentModel.Win32Exception (0x80004005): 等待操作超时 在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔型 breakConnection,Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,布尔调用者HasConnectionLock,布尔异步关闭) 在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean & dataReady) 在 System.Data.SqlClient.SqlDataReader.TryCloseInternal(布尔 closeReader) 在 System.Data.SqlClient.SqlDataReader.Close() 在 System.Data.Common.DbDataReader.Dispose(布尔处理) 在 System.Data.Common.DbDataReader.Dispose() 在 System.Data.Common.Internal.Materialization.Shaper1.Finally() at System.Data.Common.Internal.Materialization.Shaper1.SimpleEnumerator.Dispose() 在 System.Collections.Generic.List1..ctor(IEnumerable1 集合) 在 System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at ClientsToProfitsKendoUI.DAL.GenericRepository1.Get(Expression1 filter, Func2 orderBy, String includeProperties)

【问题讨论】:

  • 这通常意味着 SQL 中发生了类型转换。当datetime 被转换为nvarchar 时,我已经看到了这种情况。通过代码发送查询窗口中需要
  • 您实现所有 44K 记录只是为了获取状态?

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


【解决方案1】:

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

您还在实际选择任何数据之前按状态进行排序,这对于对任意数据进行排序是无用的练习。

从您的 Get 方法中,删除 ToList 调用。并通过首先选择State,然后调用Distinct,然后进行排序来优化您的查询。这允许数据库以最佳方式完成其工作。

如果您需要完全实现列表,请在最后致电ToList。但在那之前,请继续使用您的查询返回的IQueryable。这样您就可以让 Entity Framework 尽可能多地卸载到数据库。

【讨论】:

  • 谢谢我也跟着这个并从Get方法中删除了所有的列表
【解决方案2】:

您正在物化数据库中的每一行,只是为了选择不同的状态。让数据库为您完成繁重的工作并简单地返回状态,而不是具体化所有内容然后让 .Net 完成。

将此添加到您的 ZipCodeRepository

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

请注意,导致具体化(以及大量开销)的是ToList()

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

或者,如果您删除ToList() 调用并将Get 函数的返回类型更改为IQueryable&lt;TEntity&gt;,也应该可以解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多