简单的LINQ to Entities更新抛出'Timeout expired'

时间:2012-07-02 14:33:48

标签: c# entity-framework exception-handling linq-to-entities timeout

下面的简单方法是抛出超时错误,我无法弄清楚为什么会这样。这可以连续多次执行,我想知道这是否可能是原因?

public static Boolean UpdateMessageState(int messageId, int stateId, string message)
{
    var repo = new MailItemRepository();
    try
    {
        var objTask = repo.GetMailByMailId(messageId);

        objTask.State = stateId;
        objTask.Result = message;
        repo.Save();

        return true;
    }
    catch (Exception ex)
    {
        logger.Info(ex.Message);
        logger.Info(ex.InnerException);
        return false;
    }
}

错误追踪:

2012-07-02 15:26:38.1002|INFO|EF.Methods.MailMethods.UpdateMessageState|System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
The statement has been terminated.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)

修改

我已从等式中删除了LINQ,现在将其作为UpdateMessageState

public static Boolean UpdateMessageState(int messageId, int stateId, string message)
    {

        var success = true;

        var conn =
            new SqlConnection(
                "Data Source=...");

        try
        {

            //logger.Info(String.Format("S1:messageId={0},stateId={1},message={2}", messageId, stateId, message));

            var cmdPers = new SqlCommand("procMailQueueStatusUpdate", conn)
                              {
                                  CommandType = CommandType.StoredProcedure
                              };

            cmdPers.Parameters.Add("@MessageId", SqlDbType.Int);
            cmdPers.Parameters.Add("@StateId", SqlDbType.Int);
            cmdPers.Parameters.Add("@Message", SqlDbType.VarChar, -1);

            cmdPers.Parameters["@MessageId"].Value = messageId;
            cmdPers.Parameters["@StateId"].Value = stateId;
            cmdPers.Parameters["@Message"].Value = message;

            conn.Open();
            cmdPers.ExecuteNonQuery();

        }
        catch (Exception ex)
        {
            logger.Info(ex.Message);
            success = false;
        }
        finally
        {
            if (conn.State == ConnectionState.Open)
            {
                conn.Close();
                conn.Dispose();
            }
        }
        return success;
    }
}

1 个答案:

答案 0 :(得分:5)

我的猜测是sql sever的响应速度比你想象的慢一点。这可能是由几件事(内存压力,磁盘IO,资源等待,网络延迟等)引起的。

只是增加连接的超时,你应该是金色的。您可以进行此更改,添加" Connect Timeout"关键字到当前连接字符串

http://www.connectionstrings.com/Articles/Show/all-sql-server-connection-string-keywords

Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;Connect Timeout=60

如果失败,请尝试增加命令超时。使用ADO时,您可以按照以下步骤进行操作。

using (SqlConnection con = new SqlConnection())
using(SqlCommand cmd = new SqlCommand())
{            
    cmd.CommandTimeout = 60;
    cmd.Connection = con;
}

要在linq中将此属性设置为实体,请使用以下方法

using (MyEntities db = new MyEntities())
{
  db.CommandTimeout = 60;
}