Тайм-аут вызова хранимой процедуры SQL Server из C # через ado.net - PullRequest
3 голосов
/ 05 декабря 2011

Я создал хранимую процедуру в SQL Server, который запускается сразу из Management Studio.

При вызове хранимой процедуры из кода с точно такими же параметрами время ожидания истекает.

Хранимая процедура принимает много параметров, большинство из которых имеют значение NULL в качестве значения по умолчанию.Я попытался присвоить параметры объекту SqlCommand несколькими способами:

  • Не добавлять параметры для нулевых значений
  • Добавлять параметры для нулевых значений и передавать в качестве значения DBNull.Значение
  • Использование SQLCommandBuilder.DeriveParameters и присвоение только ненулевых значений

Sp принимает среди прочих 2 datetime параметров.Когда диапазон этих дат мал, запрос выполняется, но для больших диапазонов (3 месяца или около того), когда я пытаюсь выполнить метод ExecuteReader, я получаю SqlException - Timeout expired.Возвращаемых строк не так много (около 3500).

Чтобы увидеть, что происходит с процессами, я запускаю следующий запрос, когда метод ExecuteReader начинает запускаться

SELECT st.text AS [SQL Text],
       w.session_id, 
       w.wait_duration_ms,
       w.wait_type, w.resource_address, 
       w.blocking_session_id, 
       w.resource_description 
FROM sys.dm_os_waiting_tasks AS w
INNER JOIN sys.dm_exec_connections AS c ON w.session_id = c.session_id 
CROSS APPLY (SELECT * FROM sys.dm_exec_sql_text(c.most_recent_sql_handle)) AS st 
WHERE w.session_id > 50
  AND w.wait_duration_ms > 0

и я получаю результаты, подобные следующим.Это нормально?

SQL Text    session_id  wait_duration_ms    wait_type   resource_address    blocking_session_id resource_description
CREATE PROCEDURE [dbo].[GetVoucherJobs]...  64  23993   CXPACKET    0x000000008012A870  64  exchangeEvent id=port801283d0 nodeId=0
CREATE PROCEDURE [dbo].[GetVoucherJobs]...  64  15  IO_COMPLETION   NULL    NULL    NULL
CREATE PROCEDURE [dbo].[GetVoucherJobs]...  64  15  IO_COMPLETION   NULL    NULL    NULL
CREATE PROCEDURE [dbo].[GetVoucherJobs]...  64  2121    CXPACKET    0x000000008012BE60  64  exchangeEvent id=port801283d0 nodeId=0

Если вместо вызова хранимой процедуры я запускаю запрос, устанавливая CommandText в теле sp, он запускается немедленно.Это моя хранимая процедура:

CREATE PROCEDURE [dbo].[GetVoucherJobs] 
    @sUsrClientCode NVARCHAR(50),
    @dFr DATETIME = NULL,
    @dTo DATETIME = NULL,
    @sVchSerial NVARCHAR(50) = NULL,
    @sConName NVARCHAR(50) = NULL,
    @sJobOrderId NVARCHAR(50) = NULL,
    @sUsrName NVARCHAR(50) = NULL,
    @bJobClosed BIT = NULL,
    @bJobCanceled BIT = NULL,
    @bCount BIT = 0,
    @bGTCostCenter BIT = 0 
AS
BEGIN
    SET NOCOUNT ON

    IF @bCount = 0
    BEGIN
        IF @bGTCostCenter = 0
        BEGIN
            SELECT CASE WHEN sfVchBelongsTo IS NULL THEN sVchSerial ELSE sfVchBelongsTo END, Jobs.*,
                nkVch, sVchConName, sVchConAddress, sVchConCity, sVchConTel, sVchConZip, sVchDest, sVchCourier,
                sVchSerial, nVchPieces, cVchWeight, sVchDesc, sVchAdditional, cVchTotal, sVchStatus,
                sVchSubCode, sfVchBelongsTo, cVchInsAmount, nfVchJob, sUsrName
            FROM Jobs
            INNER JOIN Users ON nfJobUser = nkUsr
            INNER JOIN Vouchers ON nfVchJob = nkJob
            WHERE nfVchLinkedTo IS NULL AND
            sUsrClientCode = @sUsrClientCode AND
            (@dFr IS NULL OR dJob >= @dFr) AND
            (@dTo IS NULL OR dJob <= @dTo) AND
            (@sVchSerial IS NULL OR sVchSerial LIKE (@sVchSerial + '%')) AND
            (@sConName IS NULL OR sVchConName LIKE (@sConName + '%')) AND
            (@sJobOrderId IS NULL OR sJobOrderId LIKE (@sJobOrderId + '%')) AND
            (@sUsrName IS NULL OR sUsrName = @sUsrName) AND
            (@bJobClosed IS NULL OR bJobClosed = @bJobClosed) AND
            (@bJobCanceled IS NULL OR bJobCanceled = @bJobCanceled)
            ORDER BY 1, nkJob
        END
        ELSE
        BEGIN
            SELECT CASE WHEN sfVchBelongsTo IS NULL THEN sVchSerial ELSE sfVchBelongsTo END, Jobs.*,
                nkVch, sVchConName, sVchConAddress, sVchConCity, sVchConTel, sVchConZip, sVchDest, sVchCourier,
                sVchSerial, nVchPieces, cVchWeight, sVchDesc, sVchAdditional, cVchTotal, sVchStatus,
                COALESCE(κωδικος, '') AS sVchSubCode, sfVchBelongsTo, cVchInsAmount, nfVchJob, sUsrName
            FROM Jobs
            INNER JOIN Users ON nfJobUser = nkUsr
            INNER JOIN Vouchers ON nfVchJob = nkJob
            LEFT JOIN _ΠΕΛΑΤΕΣ_ΚΕΝΤΡΑ_ΧΡΕΩΣΗΣ ON sVchSubCode = Περιγραφη AND Πελατης = sUsrClientCode
            WHERE nfVchLinkedTo IS NULL AND
            sUsrClientCode = @sUsrClientCode AND
            (@dFr IS NULL OR dJob >= @dFr) AND
            (@dTo IS NULL OR dJob <= @dTo) AND
            (@sVchSerial IS NULL OR sVchSerial LIKE (@sVchSerial + '%')) AND
            (@sConName IS NULL OR sVchConName LIKE (@sConName + '%')) AND
            (@sJobOrderId IS NULL OR sJobOrderId LIKE (@sJobOrderId + '%')) AND
            (@sUsrName IS NULL OR sUsrName = @sUsrName) AND
            (@bJobClosed IS NULL OR bJobClosed = @bJobClosed) AND
            (@bJobCanceled IS NULL OR bJobCanceled = @bJobCanceled)
            ORDER BY 1, nkJob
        END
    END
    ELSE
    BEGIN
        SELECT COUNT(*) FROM Jobs
        INNER JOIN Users ON nfJobUser = nkUsr
        INNER JOIN Vouchers ON nfVchJob = nkJob
        WHERE nfVchLinkedTo IS NULL AND
        sUsrClientCode = @sUsrClientCode AND
        (@dFr IS NULL OR dJob >= @dFr) AND
        (@dTo IS NULL OR dJob <= @dTo) AND
        (@sVchSerial IS NULL OR sVchSerial LIKE (@sVchSerial + '%')) AND
        (@sConName IS NULL OR sVchConName LIKE (@sConName + '%')) AND
        (@sJobOrderId IS NULL OR sJobOrderId LIKE (@sJobOrderId + '%')) AND
        (@sUsrName IS NULL OR sUsrName = @sUsrName) AND
        (@bJobClosed IS NULL OR bJobClosed = @bJobClosed) AND
        (@bJobCanceled IS NULL OR bJobCanceled = @bJobCanceled)
    END
END

Я нашел похожий вопрос, но без ответа: Asp.Net выдает ошибку времени ожидания при запуске хранимой процедуры

Здесьэто код:

SqlCommand oCommand = new SqlCommand("GetVoucherJobs");
SqlConnection oConnection;
Result eResult = OpenConnection(out oConnection);
if(eResult != Result.Ok) return new GetJobsResult { eResult = eResult };

oCommand.CommandType = CommandType.StoredProcedure;
oCommand.Connection = oConnection;
oCommand.Parameters.AddWithValue("@sUsrClientCode", oParams.ClientCode);
oCommand.Parameters.AddWithValue("@dFr", oParams.DateFrom == Utils.dNull ? Utils.dNull : oParams.DateFrom);
oCommand.Parameters.AddWithValue("@dTo", oParams.DateTo == Utils.dNull ? DateTime.MaxValue : oParams.DateTo);
oCommand.Parameters.Add("@sVchSerial", SqlDbType.NVarChar);
if(oParams.VoucherNumber != "") oCommand.Parameters["@sVchSerial"].Value = oParams.VoucherNumber;
oCommand.Parameters.Add("@sConName", SqlDbType.NVarChar);
if(oParams.ConsigneeName != "") oCommand.Parameters["@sConName"].Value = oParams.ConsigneeName;
oCommand.Parameters.Add("@sUsrName", SqlDbType.NVarChar);
if(oParams.UserName != "") oCommand.Parameters["@sUsrName"].Value = oParams.UserName;
oCommand.Parameters.Add("@sJobOrderId", SqlDbType.NVarChar);
if(oParams.OrderId != "") oCommand.Parameters["@sJobOrderId"].Value = oParams.OrderId;
oCommand.Parameters.Add("@bJobClosed", SqlDbType.Bit);
oCommand.Parameters.Add("@bJobCanceled", SqlDbType.Bit);
if(oParams.State != VoucherState.All) {
    oCommand.Parameters["@bJobClosed"].Value = oParams.State == VoucherState.Open ? 0 : 1;
    if(oParams.State == VoucherState.ClosedActive || oParams.State == VoucherState.ClosedCanceled) {
        oCommand.Parameters["@bJobCanceled"].Value = oParams.State == VoucherState.ClosedActive ? 0 : 1;
    }
}
oCommand.Parameters.AddWithValue("@bGTCostCenter", oParams.UseGTCostCenter);
oCommand.Parameters.AddWithValue("bCount", 0);

SqlDataReader oReader = oCommand.ExecuteReader();

1 Ответ

1 голос
/ 05 декабря 2011

Если вы получаете разные результаты из Management Studio, возможно, что некоторые параметры вашего подключения отличаются - например, ANSI_NULLS, ANSI_PADDING.

Попробуйте явно указать их в своем SP - это может помочь вам получить то же поведение в Management Studio и .NET, что поможет с вашей диагностикой.

...