r3plica
Well-known member
- Joined
- Mar 4, 2010
- Messages
- 86
- Programming Experience
- 3-5
I have seen this question asked before, but I am struggling.
I have created a stored procedure which is pretty complicated.
Here it is for reference:
This proc takes about 1 second to run in SQL Studio Manager, but when I called this from my code:
FillDataTable takes forever. Infact it times out.
Now I have stepped through my code and it is actually when I run the ExecuteReader command that it takes ages.
I can't understand why it would only take a second to run in T-SQL but over 2 minutes from my application.
Could someone please help me to fix this issue as it has happened on another report and is beginning to annoy me
Here is my BaseDataAcess.vb so you can see the offending code:
I have created a stored procedure which is pretty complicated.
Here it is for reference:
VB.NET:
ALTER PROC ChangeoverEffeciencyReport
@DateFrom DATETIME
, @DateTo DATETIME
AS
BEGIN
CREATE TABLE #Temp
(
DepartmentID INT NOT NULL
, Department VARCHAR(10) NOT NULL
, PlanEfficiency DECIMAL(12, 2) NOT NULL
, ChangeEfficiency DECIMAL(12, 2) NOT NULL
, CostStandard INT NOT NULL
, PlanStandard INT NOT NULL
, Actual INT NOT NULL
, HasBeenUpdated BIT NOT NULL
)
INSERT #Temp
SELECT
c.ID
, c.DepartmentCode
, 0
, 0
, 0
, 0
, 0
, 0
FROM WorkCentreLog AS a
INNER JOIN WorkCentre AS b
ON a.WorkCentreID = b.ID
INNER JOIN Department AS c
ON b.DepartmentID = c.ID
WHERE a.Date
BETWEEN @DateFrom
AND @DateTo
GROUP BY
c.ID
, c.DepartmentCode
DECLARE @ID VARCHAR(10)
SELECT TOP 1 @ID = DepartmentID
FROM #Temp
ORDER BY DepartmentID
WHILE @ID <> ''
BEGIN
-- First set to has been updated
Update #Temp
SET HasBeenUpdated = 1
WHERE Department =
(
SELECT DepartmentCode
COLLATE Latin1_General_CI_AS
FROM Department
WHERE ID = @ID
)
-- Actual
UPDATE #Temp
SET Actual =
(
SELECT ISNULL(SUM((DATEDIFF(Minute, StartTime, FinishTime))), 0)
FROM WorkCentreLog
WHERE Date
BETWEEN @DateFrom
AND @DateTo
AND EventID IN
(
SELECT ID
FROM Event
WHERE EventGroupID =
(
SELECT ID FROM EventGroup WHERE UPPER(Description) = 'CHANGEOVER'
)
)
AND WorkCentreID IN
(
SELECT ID
FROM WorkCentre
WHERE DepartmentID = @ID
)
)
WHERE Department =
(
SELECT DepartmentCode
COLLATE Latin1_General_CI_AS
FROM Department
WHERE ID = @ID
)
-- CostStandard
UPDATE #Temp
SET CostStandard =
(
SELECT SUM(t.CostStandard)
FROM
(
SELECT
(
SELECT CostStandard
FROM Process
WHERE ID = WorkCentreLog.ProcessID
) AS CostStandard
FROM WorkCentreLog
WHERE Date
BETWEEN @DateFrom
AND @DateTo
AND EventID IN
(
SELECT ID
FROM Event
WHERE EventGroupID =
(
SELECT ID FROM EventGroup WHERE UPPER(Description) = 'CHANGEOVER'
)
)
AND WorkCentreID IN
(
SELECT ID
FROM WorkCentre
WHERE DepartmentID = 7
)
) AS t
)
/*
-- PlanStandard
UPDATE #Temp
SET PlanStandard =
(
SELECT SUM(t.PlanStandard)
FROM
(
SELECT
(
SELECT PlanStandard
FROM Process
WHERE ID = WorkCentreLog.ProcessID
) AS CostStandard
FROM WorkCentreLog
WHERE Date
BETWEEN @DateFrom
AND @DateTo
AND EventID IN
(
SELECT ID
FROM Event
WHERE EventGroupID =
(
SELECT ID FROM EventGroup WHERE UPPER(Description) = 'CHANGEOVER'
)
)
AND WorkCentreID IN
(
SELECT ID
FROM WorkCentre
WHERE DepartmentID = 7
)
) AS t
)*/
SELECT TOP 1 @ID = DepartmentID
FROM #Temp
WHERE HasBeenUpdated = 0
ORDER BY DepartmentID
-- If nothing was returned
IF @@ROWCOUNT = 0
SET @ID = ''
END
SELECT
*
FROM #Temp
DROP TABLE #Temp
END
GO
This proc takes about 1 second to run in SQL Studio Manager, but when I called this from my code:
VB.NET:
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Imports MachineTracker.Common
Public Class ChangeoverEfficiencyDataAccess
Inherits BaseDataAccess
Public Shared Function SelectEfficiencyByDate(ByVal DateFrom As DateTime, ByVal DateTo As DateTime) As EfficiencyCollection
Dim wEfficiency As New EfficiencyCollection
Dim dt As DataTable
Dim SQLCmd As New SqlCommand
SetConnectionString = ConfigurationManager.ConnectionStrings("myMachineTracker").ConnectionString
SQLCmd.CommandType = CommandType.StoredProcedure
SQLCmd.CommandText = "ChangeoverEffeciencyReport"
SQLCmd.CommandTimeout = 200
SQLCmd.Parameters.Add("@DateFrom", SqlDbType.DateTime).Value = DateFrom
SQLCmd.Parameters.Add("@DateTo", SqlDbType.DateTime).Value = DateTo
dt = FillDataTable(SQLCmd)
For Each dr As DataRow In dt.Rows
wEfficiency.Add(ParseEfficiency(dr))
Next
Return wEfficiency
End Function
Private Shared Function ParseEfficiency(ByVal dr As DataRow) As Efficiency
Dim coEff As New Efficiency
With coEff
.DepartmentID = CInt(dr("DepartmentID"))
.DepartmentCode = Trim(dr("Department"))
.ChangeEfficiency = CDbl(dr("ChangeEfficiency"))
.PlanEfficiency = CDbl(dr("PlanEfficiency"))
.CostStandard = CInt(dr("CostStandard"))
.PlanStandard = CInt(dr("PlanStandard"))
.Actual = CInt(dr("Actual"))
End With
Return coEff
End Function
End Class
FillDataTable takes forever. Infact it times out.
Now I have stepped through my code and it is actually when I run the ExecuteReader command that it takes ages.
I can't understand why it would only take a second to run in T-SQL but over 2 minutes from my application.
Could someone please help me to fix this issue as it has happened on another report and is beginning to annoy me
Here is my BaseDataAcess.vb so you can see the offending code:
VB.NET:
Imports System.Data
Imports System.Data.SqlClient
Public MustInherit Class BaseDataAccess
Private Shared mstrConnectionString As String
Private Shared mConn As SqlConnection
Public Shared WriteOnly Property SetConnectionString() As String
Set(ByVal value As String)
mstrConnectionString = value
End Set
End Property
Shared Function FillDataTable(ByVal pSQLCmd As SqlCommand) As DataTable
Dim dr As SqlDataReader
Dim dt As New DataTable
If mstrConnectionString <> "" Then
OpenConnection()
pSQLCmd.Connection = mConn ' Set our connection
dr = pSQLCmd.ExecuteReader
dt.Load(dr) ' Load the DataRead into our DataTable
dr.Close()
CloseConnection() ' Call our Sub
Else
Throw New ApplicationException("Connection String has not been set")
End If
Return dt
End Function
Shared Function FillDataSet(ByVal pSQLCmd As SqlCommand) As DataSet
Dim ds As New DataSet
Dim da As New SqlDataAdapter
If mstrConnectionString <> "" Then
OpenConnection()
pSQLCmd.Connection = mConn ' Set our connection
da.SelectCommand = pSQLCmd ' Set the SelectCommand
da.Fill(ds) ' Fill our DataSet
da.Dispose() ' Dispose our Data Adapter
CloseConnection() ' Call our Sub
Else
Throw New ApplicationException("Connection String has not been set")
End If
Return ds
End Function
Shared Sub ExecuteNonSelect(ByVal pSQLCmd As SqlCommand)
If mstrConnectionString <> "" Then
OpenConnection() ' Call our Sub
pSQLCmd.Connection = mConn ' Set our connection
pSQLCmd.ExecuteNonQuery() ' Execute
CloseConnection() ' Call our Sub
Else
Throw New ApplicationException("Connection String has not been set")
End If
End Sub
Private Shared Sub OpenConnection()
mConn = New SqlConnection ' Create our connection
mConn.ConnectionString = mstrConnectionString ' Set our ConnectionString
mConn.Open() ' Open the connection
End Sub
Private Shared Sub CloseConnection()
If mConn.State = ConnectionState.Open Then
mConn.Close() ' Close
mConn.Dispose() ' Dispose
End If
End Sub
End Class