一般的なタイプの質問があります。SQL Server ストアド プロシージャを呼び出す C# アプリケーションがあり、C# アプリケーションがタイムアウトした場合、サーバー上のプロシージャ コールは最後まで実行されますか?
5 に答える
いいえ。以下は複製です。タイムアウトが発生すると、実行中のプロセスが強制終了され、すぐに停止します。トランザクションが指定されていない場合、タイムアウト前にストアド プロシージャで実行された作業は永続化されます。同様に、サーバーへの接続が外力によって切断された場合、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 からストアド プロシージャを実行すると、1 分間で 6 行が追加されます。
簡単な答えは「はい」です....ここに私の主張を裏付ける情報があります
アプリケーションが「タイムアウト」する可能性がある場所は実際にはいくつかありますが、その 1 つはコマンド実行のタイムアウトです ...
コマンド実行タイムアウト- このプロパティは、コマンドの実行中または結果の処理中のすべてのネットワーク読み取りの累積タイムアウトです。最初の行が返された後もタイムアウトが発生する可能性があり、ユーザーの処理時間は含まれず、ネットワークの読み取り時間のみが含まれます。
タイムアウトした場合、コマンドはそれ自体でロールバックしません。タイムアウトした場合、コードの周りにトランザクションが必要になります。
行が返されるときにタイムアウトが発生する可能性がある場合は、C# が SQL Server にコマンドの実行を停止するように指示しないということよりも、いつでもタイムアウトが発生する可能性があることを意味します。コマンドをトランザクションにラップするなど、それについて行うことができます
ソース: https://blogs.msdn.microsoft.com/mattn/2008/08/29/sqlclient-timeouts-revealed/ ... そして経験
それについての私の考えは、すべてはプロシージャーの呼び出しによって開かれた接続に関するものだということです。コードが using ブロック内で実行された場合、またはガベージ コレクションが行われた場合、SP の実行はロールバックされると思います。
SQlCommand クラスを使用している場合、アプリがタイムアウトすると、クエリの実行がロールバックされます。