I have created a stored procedure in SQL Server, which runs immediately from Management Studio.
When calling the stored procedure from code, with exact the same parameters, it times out.
The stored procedure accepts many parameters, that most have NULL as default value. I have tried assigning parameters to the SqlCommand object with a number of ways:
- Not adding parameters for null values
- Adding parameters for null values and pass as a value DBNull.Value
- Using SQLCommandBuilder.DeriveParameters and assigning only the non null values
Sp takes among others 2 datetime parameters. When the range of these dates is small the query runs, but for larger ranges (3 months or so), when I try to execute the ExecuteReader method I get a SqlException - Timeout expired. The rows to be returned are not much (around 3500).
In an effort to see what’s happening with the processes, I run the following query when the ExecuteReader method starts to run
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
and I get results like the following. Is it normal?
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
If instead of calling the stored procedure, I run the query through setting the CommandText to sp’s body it runs immediately. This my stored procedure:
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
I found a similar question, but with no answer:
Asp.Net Gives a Timeout Error While Running a Stored Procedure
Here is the code:
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();
If you get different results from Management Studio, it may be that some of your connection settings are different – e.g. ANSI_NULLS, ANSI_PADDING.
Try setting them explicitly in your SP – this may help you get the same behavior in Management Studio and .NET, which will help with your diagnosis.