如果我的C#超时存储过程调用,该过程是否继续运行?

时间:2016-04-21 14:42:35

标签: c# sql-server stored-procedures command-timeout

我只是一般的问题。如果我有一个调用SQL Server存储过程的C#应用​​程序,并且C#应用程序超时,那么服务器上的过程调用是否继续运行到它的完成?

5 个答案:

答案 0 :(得分:2)

简短回答是......这里有一些信息可以支持我的索赔

实际上有几个地方应用程序可以'超时',但其中一个是命令执行超时......

命令执行超时 - 此属性是命令执行或处理结果期间所有网络读取的累计超时。返回第一行后仍可能发生超时,并且不包括用户处理时间,仅包括网络读取时间。

如果命令超时,它将不会自行回滚。如果超时,这将需要围绕代码进行交易。

如果在返回行时发生超时,则意味着任何时候都可能发生超时C#不会告诉SQL Server停止运行该命令。可以采取相关措施,例如在事务中包装命令

来源:https://blogs.msdn.microsoft.com/mattn/2008/08/29/sqlclient-timeouts-revealed/ ...和经验

答案 1 :(得分:1)

没有。以下是复制品。超时发生时,正在运行的进程将被终止,并立即停止。如果未指定事务,则将在超时之前在存储过程中完成的工作将保留。同样,如果某些外部力量切断了与服务器的连接,SQL Server将终止正在运行的进程。

using (var conn = new SqlConnection(@"Data Source=.;Initial Catalog=Test;Integrated Security=True"))
{
    conn.Open();

    using (var setupTable = new SqlCommand(@"
        IF NOT EXISTS (
            SELECT *
            FROM
                sys.schemas s
                    INNER JOIN sys.tables t ON
                        t.[schema_id] = s.[schema_id]
            WHERE
                s.name = 'dbo' AND
                T.name = 'TimeoutTest')
        BEGIN
            CREATE TABLE dbo.TimeoutTest
            (
                ID int IDENTITY(1,1) PRIMARY KEY,
                CreateDate datetime DEFAULT(getdate())
            );
        END

        -- remove any rows from previous runs
        TRUNCATE TABLE dbo.TimeoutTest;", conn))
    {
        setupTable.ExecuteNonQuery();
    }

    using (var checkProcExists = new SqlCommand(@"
        SELECT COUNT(*)
        FROM
            sys.schemas s
                INNER JOIN sys.procedures p ON
                    p.[schema_id] = s.[schema_id]
        WHERE
            s.name = 'dbo' AND
            p.name = 'AddTimeoutTestRows';", conn))
    {
        bool procExists = ((int)checkProcExists.ExecuteScalar()) == 1;

        if (!procExists)
        {
            using (var setupProc = new SqlCommand(@"
                CREATE PROC dbo.AddTimeoutTestRows
                AS
                BEGIN

                    DECLARE @stop_time datetime;

                    SET @stop_time = DATEADD(minute, 1, getdate());

                    WHILE getdate() < @stop_time
                    BEGIN
                        INSERT INTO dbo.TimeoutTest DEFAULT VALUES;

                        -- wait 10 seconds between inserts
                        WAITFOR DELAY '0:00:10';
                    END

                END", conn))
            {
                setupProc.ExecuteNonQuery();
            }
        }
    }

    bool commandTimedOut = false;

    try
    {
        using (var longExecution = new SqlCommand("EXEC dbo.AddTimeoutTestRows;", conn))
        {
            // The time in seconds to wait for the command to execute.
            // Explicitly setting the timeout to 30 seconds for clarity.
            longExecution.CommandTimeout = 30;

            longExecution.ExecuteNonQuery();
        }
    }
    catch (SqlException ex)
    {
        if (ex.Message.Contains("Timeout"))
        {
            commandTimedOut = true;
        }
        else
        {
            throw;
        }
    }

    Console.WriteLine(commandTimedOut.ToString());

    // Wait for an extra 30 seconds to let any execution on the server add more rows.
    Thread.Sleep(30000);

    using (var checkTableCount = new SqlCommand(@"
        SELECT COUNT(*)
        FROM
            dbo.TimeoutTest t;", conn))
    {
        // Only expecting 3, but should be 6 if server continued on without us.
        int rowCount = (int)checkTableCount.ExecuteScalar();

        Console.WriteLine(rowCount.ToString("#,##0"));
    }
}

Console.ReadLine();

产生以下输出

True
3

即使从Management Studio运行存储过程,也会在一分钟的时间范围内添加6行。

答案 2 :(得分:0)

如果您正在使用SQlCommand类,则一旦应用超时,将回滚查询执行。

答案 3 :(得分:0)

我对此的想法是关于通过调用程序打开的连接的全部内容。 如果您的代码在使用块中执行或者它是垃圾收集,那么我认为SP的执行将被回滚。

答案 4 :(得分:0)

            Conn = new SqlConnection(ConnStr);
            Conn.Open();
            myCommand = new SqlCommand();
            myCommand.CommandTimeout = 180000;
            myCommand.Connection = Conn;
            myCommand.CommandType = System.Data.CommandType.StoredProcedure;