Время ожидания не истекло, но время ожидания все еще истекло (см. Код)? - PullRequest
1 голос
/ 11 мая 2009

ОК. Я получаю эту ошибку примерно через 3-4 минуты после сбоя:

 Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

Source Error:

Line 93: 
Line 94:             DataSet getData;
Line 95:             getData = SqlHelper.ExecuteDataset(ConfigurationManager.ConnectionStrings["connstr"].ConnectionString, CommandType.StoredProcedure, "Course_NewReportGet_Get_Sav", objPara);
Line 96: 
Line 97:             foreach (DataRow dr in getData.Tables[0].Rows)

Вот код, я думаю, что я что-то не так делаю, я установил тайм-аут на 5000 секунд, хотя это должно быть что-то другое. Вы заметите, что это довольно вложенный цикл вызовов процедур. Я получаю каждую компанию, затем получаю каждый курс, назначенный каждой компании, затем для каждого курса я получаю отчет обо всех действиях пользователей. Существует около 250 компаний, от 2 до 70 курсов на одну компанию и от 8 до 1000 пользователей на отчет о курсе на компанию ... поэтому мы имеем дело с большим количеством данных здесь. Этот последний вызов в отчете get является довольно массивной хранимой процедурой ...

Я пытаюсь преобразовать данные в новую форму, с которой потом будет работать быстрее и проще, но сейчас я должен разобрать, что у нас есть, и опубликовать это новым способом. Это все в одной базе данных, но я не совсем уверен, как бы я сделал все это только на SQL. В основном я использую хранимую процедуру, которая используется нашими инструментами отчетности, чтобы получить данные для публикации в новой таблице. Но мне нужно запустить процедуру для каждого курса для каждой компании, а затем опубликовать данные для каждого пользователя, возвращенные в отчете по каждому курсу от каждой компании ... Это огромно ...

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;
using Mexico.Data;

public partial class admin_tools_Optimus : System.Web.UI.Page
{
    protected int step = 0;
    protected string[] companies = new string[260];
    protected string[] coursestrings = new string[260];
    protected int total = 0;
    protected int[] totalcourses = new int[260];

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void Proceed(object sender, EventArgs e)
    {
        DataSet getCompanies = SqlHelper.ExecuteDataset(ConfigurationManager.ConnectionStrings["connstr"].ConnectionString, CommandType.StoredProcedure, "Companies_All_Get");

        int counter = 0;

        foreach (DataRow dr in getCompanies.Tables[0].Rows)
        {
            lstData.Items.Add(dr["companyid"].ToString() + ": " + dr["companyname"].ToString());
            companies[counter] = dr["companyid"].ToString();
            counter++;
        }
        lblCurrentData.Text = counter.ToString() + " companies ready, click next to get all company courses.";
        total = counter;

        GetCompanies();
    }


    protected void GetCompanies()
    {
        string[,] courses = new string[260, 200];

        for (int i = 0; i < total-1; i++)
        {
            DataSet getBundles = SqlHelper.ExecuteDataset(ConfigurationManager.ConnectionStrings["connstr"].ConnectionString, CommandType.StoredProcedure, "CompanyCourses_ByCompanyID_Get_Sav", new SqlParameter("@companyid", companies[i]));

            int counter = 0;

            foreach (DataRow dr in getBundles.Tables[0].Rows)
            {
                courses[i, counter] = dr["bundleid"].ToString();
                counter++;
            }

            string allID = "";

            allID += courses[i, 0];

            for (int ii = 0; ii < counter; ii++)
            {
                allID += "," + courses[i, ii];
            }
            Response.Write(allID + " <br/>");
            coursestrings[i] = allID;
            totalcourses[i] = counter;
        }
        GetUsers();
    }

    protected void GetUsers()
    {
        for (int i = 0; i < total - 1; i++)
        {
            SqlParameter[] objPara = new SqlParameter[10];
            objPara[0] = new SqlParameter("@CompanyID", companies[i]);
            objPara[1] = new SqlParameter("@CourseID", coursestrings[i]);
            objPara[2] = new SqlParameter("@DateRangeType", 1);
            //objPara[3] = new SqlParameter("@StartDate", startDate);
            //objPara[4] = new SqlParameter("@EndDate", System.DateTime.Now.ToString("MM/dd/yyyy"));
            objPara[5] = new SqlParameter("@UserName", "");
            objPara[6] = new SqlParameter("@StartIndex", 1);
            objPara[7] = new SqlParameter("@MaximumRows", 100000);



            DataSet getData;
            getData = SqlHelper.ExecuteDataset(ConfigurationManager.ConnectionStrings["connstr"].ConnectionString, CommandType.StoredProcedure, "Course_NewReportGet_Get_Sav", objPara);

            foreach (DataRow dr in getData.Tables[0].Rows)
            {
                Response.Write("user: " + dr["userid"].ToString() + " / course: " + dr["bundleid"].ToString() + " - progress: " + dr["viewed"].ToString() + " - scored: " + dr["scored"].ToString() + "<br/><br/>");
            }
        }
    }
}

КОД СТРАНИЦЫ:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Optimus.aspx.cs" Inherits="admin_tools_Optimus" Debug="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="lblCurrentData" runat="server" Text="Click next to get all Companies"/><br />
        <asp:Button ID="btnNext" runat="server" Text="Next" OnClick="Proceed" />
        <br/>
        <asp:ListBox ID="lstData" runat="server" height="300" Width="300" />
    </div>
    </form>
</body>
</html>

Ответы [ 3 ]

14 голосов
/ 11 мая 2009

При обращении к базе данных со страницы asp.net необходимо знать пять таймаутов:

  1. Тайм-аут соединения с базой данных Устанавливается на объекте SQLConnection, возможно, через строку соединения.
  2. Тайм-аут команды базы данных Устанавливается на объекте SQLCommand.
  3. Тайм-аут сценария ASP.Net Устанавливается на вашей странице с помощью Server.ScriptTimeout.
  4. Другие тайм-ауты IIS Установлено на вашей странице IIS. Смотрите эту ссылку: http://msdn.microsoft.com/en-us/library/ms525386.aspx?ppud=4
  5. Тайм-аут интернет-браузера Браузер / клиент будет ждать так долго. Вы не контролируете это, поэтому нет смысла беспокоиться об этом, но вы все равно должны знать, что оно существует.

Убедитесь, что вы проверили первые 4 в списке.

Обычно я бы также сказал кое-что о том, что 3+ минуты - это путь , чтобы долго ждать загрузки страницы. У вас может быть достаточно данных, чтобы оправдать время запроса, но если это так, это слишком много данных, чтобы пользователь мог реально оценить их на одной странице. Подумайте о том, чтобы разбить его. Но в этом случае кажется, что вы создаете «отчет», который нужно запускать нечасто. Несмотря на то, что я все еще подвергаю сомнению достоинства таких отчетов (слишком много данных нужно пройти вручную - выведите их в таблицу фактов или где-то подобное для извлечения дополнительных данных), я понимаю, что предприятиям все равно часто нужны их.

Также, глядя на ваш код, я вижу, где вы могли бы написать все это как один большой запрос вместо множества маленьких. Это было бы намного более эффективно для базы данных за счет некоторой дополнительной сложности при сборке ваших результатов, но результат будет работать намного быстрее. Но для чего-то, что не часто запускается, когда у вас уже есть встроенные хранимые процедуры для этого, вы не сможете оправдать переписывание вещей.

Так что я дам вам пропуск на длительную страницу ... на этот раз.

4 голосов
/ 11 мая 2009

Похоже, что при выполнении хранимой процедуры sql истекает время ожидания (исключение имеет тип SqlException). Вам необходимо увеличить время ожидания выполнения хранимой процедуры Sql, но я не думаю, что вы можете сделать это с помощью класса SqlHelper.

Вам нужно будет воспользоваться классом SqlCommand и установить там таймаут.

0 голосов
/ 11 мая 2009

Это пример крайне плохого повторного использования кода. Вместо повторного использования сохраненного процесса, который заставляет вас перебирать все входные переменные, которые вы хотите, напишите новый процесс на основе множеств, который выбирает информацию на основе объединений. Это будет намного быстрее (если, конечно, вы правильно проиндексировали). При доступе к базам данных вы не хотите делать что-либо через цикл или курсор, если возможна альтернатива на основе множеств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...