我有一个普遍的问题,对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)欢迎评论
答案 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)
在本地运行查询超时的事实表明您需要在表上使用某些索引。如果您在管理工作室中启用了“执行计划”,那么您应该能够看到需要创建哪些索引。
案例可能是因为查询超时,您将无法获得执行计划,因此您必须使用“估计执行计划”功能。 (这些图标看起来像连接在一起的蓝色和绿色小框)