12

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

4

5 回答 5

4

不,下面是复制品。当超时发生时,正在运行的进程将被杀死,立即停止它。如果您没有指定事务,则在超时之前已在存储过程中完成的工作将被保留。同样,如果与服务器的连接被某种外力切断,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 行。

于 2016-04-21T21:46:32.760 回答
2

简短的回答是肯定的....这里有一些信息可以支持我的主张

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

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

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

如果在返回行时可能发生超时,则意味着只要 C# 不会告诉 SQL Server 停止运行该命令,就会发生超时。可以做一些事情,例如将命令包装在事务中

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

于 2016-04-21T14:56:19.570 回答
0

如果您使用的是 SQlCommand 类,一旦应用程序超时,查询执行将被回滚。

于 2016-04-21T14:47:07.930 回答
0

我对此的想法是,这全都与调用过程打开的连接有关。如果您的代码在 using 块中执行,或者如果它被垃圾收集,那么我认为 SP 的执行将被回滚。

于 2016-04-21T15:33:37.150 回答
-1
            Conn = new SqlConnection(ConnStr);
            Conn.Open();
            myCommand = new SqlCommand();
            myCommand.CommandTimeout = 180000;
            myCommand.Connection = Conn;
            myCommand.CommandType = System.Data.CommandType.StoredProcedure;
于 2018-01-07T07:10:29.500 回答