我在SQL Server中創建了一個存儲過程,該存儲過程從Management Studio中立即運行。通過ado.net從C#調用SQL Server存儲過程超時
從代碼調用存儲過程時,使用完全相同的參數,超時。
存儲過程接受許多參數,大多數參數的默認值爲NULL。我曾嘗試用多種方法的參數分配SqlCommand
對象:爲空值
- 不加參數
- 添加參數爲空值,並通過作爲一個值DBNull.Value
- 使用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 Gives a Timeout Error While Running a Stored Procedure
下面是代碼:
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)立即讓存儲過程返回;如果來自ado.net的電話仍然超時,那麼你知道一些非常可怕的事情正在發生。如果是這種情況,那麼確保SQL Server 2005使用最新的服務包進行了修補(或者使用sql server 2008 express進行嘗試) - 我之前已經看到過這種行爲(在sql 2000上) – wal
請顯示您用來調用程序 –
@wal我會將生產數據庫恢復到本地副本,並希望得到相同的結果,以便測試RETURN事情。現在我正在使用最新的服務包(SP4)。 – alfoks