LINQ和.COUNT超时

时间:2009-04-06 07:04:04

标签: .net linq linq-to-sql exception

我有一个普遍的问题,对LINQ和超时的好奇心。

我正在运行一个实时应用程序,并且我正在接收以下代码的超时。

以下代码,这是正常的,我没有看到任何错误:

private static tblUser GetUserLinq(string email,string password)         {             DataContext db = new DataContext();

        var tblUsers = from user in db.tblUsers
                           where user.EmailAddress == email
                           && user.Password == password
                           select user;

        if (tblUsers.Count() == 0)
            return null;

        return tblUsers.First();
    }

但是接下来的时间有很多:

        if (tblUsers.Count() == 0)

这是例外

超时已过期。操作完成之前经过的超时时间或服务器没有响应。 - System.Data.SqlClient.SqlException:超时已过期。操作完成之前经过的超时时间或服务器没有响应。    在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection)    在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,布尔breakConnection)    在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)    在System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)    在System.Data.SqlClient.SqlDataReader.ConsumeMetaData()    在System.Data.SqlClient.SqlDataReader.get_MetaData()    在System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString)    在System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async)    在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,DbAsyncResult result)    在System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method)    在System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior,String method)    在System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior行为)    在System.Data.Common.DbCommand.ExecuteReader()    at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query,QueryInfo queryInfo,IObjectReaderFactory factory,Object [] parentArgs,Object [] userArgs,ICompiledSubQuery [] subQueries,Object lastResult)    at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query,QueryInfo [] queryInfos,IObjectReaderFactory factory,Object [] userArguments,ICompiledSubQuery [] subQueries)    at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)    在System.Data.Linq.DataQuery 1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Count[TSource](IQueryable 1来源)    在C:\ Actions.cs:行104中的Actions.GetUserLinq(String email,String password)    在C:\ Actions.cs:第33行中的登录(字符串电子邮件,字符串密码)

我对为何超时的一些看法:

计数需要计算该表中的记录数,而这不是我们所追求的 如果我们试图查找是否存在记录,那么我们应该使用以下代码:

        var tblUsers = (from user in db.tblUsers
                           where user.EmailAddress == email
                           && user.Password == password
                           select user).FirstOrDefault(u => u.UserId <0) ;

否则我对为什么LINQ在Count上超时

有点困惑

我注意到的另一件事是,如果您通过SQL企业管理器直接在计算机上运行以下SQL,它也会超时,这表明它可能是一个锁定问题,但是调用此表的唯一应用程序是LINQ

从tbluser

中选择count(userid)

欢迎评论

4 个答案:

答案 0 :(得分:3)

您应该检查用户表的索引。可能是用户名/密码索引有帮助。

答案 1 :(得分:3)

如果查询即使使用SQL Enterprise Manager超时,那么这应该是您要解决的第一件事。

完全取消LINQ - 确保 nothing else正在访问数据库,并查看该查询是否仍然超时。在其上运行查询分析器。

当然,如果您只想获得第一个用户,则应将您的方法重写为:

private static tblUser GetUserLinq(string email, string password) 
{ 
    DataContext db = new DataContext();

    var tblUsers = from user in db.tblUsers
                       where user.EmailAddress == email
                       && user.Password == password
                       select user;

    return tblUsers.FirstOrDefault();
}

(那里不需要“u =&gt; u.UserId&lt; 0”。)

如果没有结果,

FirstOrDefault已经返回null,那应该没问题。

听起来你的数据库遇到了更严重的问题。 EmailAddress和Password都被正确编入索引吗?

答案 2 :(得分:3)

顺便说一句,试着远离这种模式:

  if (tblUsers.Count() == 0)
            return null;

有一个很棒的扩展方法叫做Any(),可以为你生成更好的SQL:

if ( !tblUsers.Any())
    return null;

答案 3 :(得分:1)

在本地运行查询超时的事实表明您需要在表上使用某些索引。如果您在管理工作室中启用了“执行计划”,那么您应该能够看到需要创建哪些索引。

案例可能是因为查询超时,您将无法获得执行计划,因此您必须使用“估计执行计划”功能。 (这些图标看起来像连接在一起的蓝色和绿色小框)