I have this sub in my WinForm:
Public Function CheckSentToday(ByVal date1 As DateTime) As Boolean
Dim cmSql As New SqlCommand("Check_Today", cnSql)
Try
cmSql.CommandType = CommandType.StoredProcedure
cmSql.Parameters.AddWithValue("#date1", String.Format("{0:yyyy-MM-dd}", date1))
If Not cnSql Is Nothing AndAlso cnSql.State = ConnectionState.Closed Then cnSql.Open()
If cmSql.ExecuteScalar IsNot Nothing Then
Return True
Else
Return False
End If
Catch ex As Exception
WriteToText("CheckSentToday", ex.ToString)
CheckSentToday = False
Finally
If Not cnSql Is Nothing AndAlso cnSql.State = ConnectionState.Open Then cnSql.Close()
End Try
End Function
I am opening the connection before executing the SqlCommand,
and closing the connection in the finally clause
Still, it is returning the following error everytime this sub is called:
Description:System.InvalidOperationException: Invalid attempt to call Read when reader is closed.
at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout)
at System.Data.SqlClient.SqlDataReader.Read()
at System.Data.SqlClient.SqlCommand.CompleteExecuteScalar(SqlDataReader ds, Boolean returnSqlValue)
at System.Data.SqlClient.SqlCommand.ExecuteScalar()
Can Anyone help me figure out why?
Any help would be appreciated
Use the Using-statement instead and don't reuse the SqlConnection:
Public Function CheckSentToday(ByVal date1 As DateTime) As Boolean
Using cnSql = New SqlConnection("connection-string")
Using cmSql As New SqlCommand("Check_Today", cnSql)
cmSql.CommandType = CommandType.StoredProcedure
cmSql.Parameters.AddWithValue("#date1", String.Format("{0:yyyy-MM-dd}", date1))
Try
cnSql.Open()
If cmSql.ExecuteScalar IsNot Nothing Then
Return True
Else
Return False
End If
Catch ex As Exception
WriteToText("CheckSentToday: ", ex.ToString)
CheckSentToday = False
End Try
End Using
End Using
End Function
Related
I am running a RESTful API service which gets data from a server as a JSON string. Around 20000 rows are being selected.
Dim js As New JavaScriptSerializer()
Dim prodlist As List(Of Product) = js.Deserialize(Of List(Of Product))(JSONreturn)
The 20000 rows are populated in the list prodlist. Checked the count and manually verified the list.
I need to insert these rows in a client machine. However, while inserting the rows, it freezes or stops after inserting around 600-700 rows. Below is the code I am using for inserting.
For Each item As Product In prodlist
Dim SPName As String = "someSPname"
With connectionstring
.Clear()
.Parameters("#itemnumber", SqlDbType.VarChar, ParameterDirection.Input, , item.itemnumber
.Parameters("#itemtype", SqlDbType.VarChar, ParameterDirection.Input, , item.itemtype)
.Parameters("#DESCRIPTION", SqlDbType.VarChar, ParameterDirection.Input, , item.DESCRIPTION)
.Execute(SPName)
End With
Next
No error is thrown. It just freezes after inserting roughly 600-700 rows everytime.
Bulk insert is not an option. How do I resolve this?
UPDATE : Adding connection class. Pretty sure there is no issue with this :
Public Class ConnectionClass
Public ReadOnly Property ConnectionString() As String
Get
Return GetConfiguration()
End Get
End Property
Public Sub Parameters(ByVal param_name As String, ByVal type As SqlDbType, ByVal direction As ParameterDirection, Optional param_size As Int32 = Nothing, Optional param_value As Object = Nothing)
Dim sqlParam As SqlParameter = Nothing
Try
sqlParam = New SqlParameter(param_name, type)
sqlParam.Size = param_size
sqlParam.Direction = direction
sqlParam.Value = param_value
Lstparam.Add(sqlParam)
Finally
If sqlParam IsNot Nothing Then
sqlParam = Nothing
End If
End Try
End Sub
Public Sub Execute(ByVal strSpName As String, Optional ByVal Type As CommandType = CommandType.StoredProcedure)
Try
sqlcmd = New SqlCommand()
sqlcmd.Connection = connection
''Setting the timeout to 50 mins as setup in the previous application
sqlcmd.CommandTimeout = 3000
If transaction IsNot Nothing Then
sqlcmd.Transaction = transaction
End If
sqlcmd.CommandType = Type
sqlcmd.CommandText = strSpName
For Each argument As SqlParameter In Lstparam
sqlcmd.Parameters.Add(argument)
Next
For introw As Integer = 0 To sqlcmd.Parameters.Count - 1
If sqlcmd.Parameters.Item(introw).ParameterName.Contains("Parameter") Then
sqlcmd.Parameters.Item(introw).ParameterName = String.Empty
End If
Next
sqlcmd.ExecuteNonQuery()
Catch ex As Exception
Throw
End Try
End Sub
Public Sub Clear()
ClearParameters()
Lstparam.Clear()
End Sub
Public Sub ClearParameters()
If Not sqlcmd Is Nothing Then
Do Until sqlcmd.Parameters.Count = 0
sqlcmd.Parameters.Clear()
Loop
End If
End Sub
Public Function GetConfiguration() As String
Dim sbConnectionString As New StringBuilder
With sbConnectionString
.Append("Data Source=")
.Append(ServerName)
.Append(";")
.Append("Initial Catalog =")
.Append(DatabaseName)
.Append(";")
.Append("User ID =")
.Append(UserName)
.Append(";")
.Append("Password =")
.Append(UserPassword)
End With
Return sbConnectionString.ToString()
End Function
Public Function CreateClientConnection() As SqlConnection
Dim connectionString As String
Try
connectionString = GetConfiguration()
Dim substrings() As String = connectionString.ToUpper.Split(";")
Dim substrings1() As String = connection.ConnectionString.ToUpper.Split(";")
If Not (connection.State = ConnectionState.Open) Then
connection.ConnectionString = connectionString
connection.Open()
ElseIf Not (Trim(substrings(0)) = Trim(substrings1(0))) Then
If connection IsNot Nothing Then
connection.Dispose()
End If
connection.ConnectionString = connectionString
connection.Open()
End If
Return connection
Catch ex As Exception
If connection IsNot Nothing Then
connection.Dispose()
End If
Throw ex
End Try
End Function
End Class
I have main windows form on which i have user control. From there I do some operation related to database. During database process I show user additional windows form so he can see nice circural graphic in meantime. I use task to place mentioned database process and from there if error occurs I want to show error message from try/catch. Unfortunetly MessageBox.Show is not showing up when i do tests - catch is even not reached. Could you help me out what is wrong. I am talking about this line in catch statment:
Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
Here's circural window's form code:
Public Class FrmCircularProgress
Sub New(progressType As DevComponents.DotNetBar.eCircularProgressType)
InitializeComponent()
CircularProgress1.ProgressBarType = progressType
StartCircular()
End Sub
Public Sub StartCircular()
Me.CircularProgress1.IsRunning = True
End Sub
Public Sub StopCircular()
Me.CircularProgress1.IsRunning = False
End Sub
End Class
This is example how i use it with Task:
Dim createArticle As New Artikel
Dim pic As New FrmCircularProgress(eCircularProgressType.Donut)
Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
'--Run lenghty task
Dim resu = False
Try
resu = createArticle.ProcessArticle(_artikelsAndTheirVariationsFinal)
'--Close form once done (on GUI thread)
Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
Finally
pic.Invoke(New Action(Sub() pic.StopCircular()))
pic.Invoke(New Action(Sub() pic.Close()))
End Try
Return resu
End Function)
'--Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
...
And just for you to see example database process in our case ProcessArticle which is returning either true or false
Public Function ProcessArticle(artikel As ArticlesVariations) As Boolean
Dim result = True
Dim strcon = New AppSettingsReader().GetValue("ConnectionString", GetType(System.String)).ToString()
Using connection As New SqlConnection(strcon)
'-- Open generall connection for all the queries
connection.Open()
'-- Make the transaction.
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)
Dim newArticleRowId As Integer = 0
Dim articleIndex As Integer = 0
Try
For Each kvp As KeyValuePair(Of Integer, Artikel) In artikel.collection
Dim ckey As Integer = kvp.Key
articleIndex = kvp.Key 'save article key
Dim data As Artikel = kvp.Value
'-- If given article contains images list (artikel_images is a list with pictures associated with article)
If Not IsNothing(artikel.collection(articleIndex).ArtikelImages) Then
For Each img In artikel.collection(articleIndex).ArtikelImages
'--Insert article's images if exists
Using cmd As New SqlCommand("INSERT INTO T_Article_Image (Path, FK_Artikel_ID, Position) VALUES (#Path, #FK_Artikel_ID, #Position)", connection)
cmd.CommandType = CommandType.Text
cmd.Connection = connection
cmd.Transaction = transaction
cmd.Parameters.AddWithValue("#Path", img.Path)
cmd.Parameters.AddWithValue("#FK_Artikel_ID", newArticleRowId)
cmd.Parameters.AddWithValue("#Position", img.Position)
cmd.ExecuteScalar()
End Using
Next
End If
'-- If given article contains articles variations list (artikel_variation_attributes is a list with variations associated with article)
If Not IsNothing(artikel.collection(articleIndex)._artikel_variation_attributes) Then
For Each var In artikel.collection(articleIndex)._artikel_variation_attributes
'--Insert article's images if exists
Using cmd As New SqlCommand("INSERT INTO T_Artikel_T_Variation (FK_Variation_VariationAttribute_ID, FK_Artikel_ID, Position) VALUES (#FK_Variation_VariationAttribute_ID, #FK_Artikel_ID, #Position)", connection)
cmd.CommandType = CommandType.Text
cmd.Connection = connection
cmd.Transaction = transaction
cmd.Parameters.AddWithValue("#FK_Variation_VariationAttribute_ID", New Variation_VariationAttribute(var.FkVariationId, var.FkVariationAttributeId).GetId())
cmd.Parameters.AddWithValue("#FK_Artikel_ID", newArticleRowId)
cmd.Parameters.AddWithValue("#Position", var.Position)
cmd.ExecuteScalar()
End Using
Next
End If
Next
transaction.Commit()
Catch ex As Exception
result = False
'-- Roll the transaction back.
Try
transaction.Rollback()
Catch ex2 As Exception
result = False
End Try
End Try
End Using
Return result
End Function
I would not expect your catch to be reached. In your ProcessArticle function you have another Try .. Catch If there is an error in the SQL operation, this is where it will be caught. You then return false! So the calling routine does not catch the error, because it has already been handled gracefully. If you want to catch the error in your calling routine, then you will need to Raise an error from your catch in the ProcessArticle function.
You could change your Try Catch in ProcessArticle to
Catch ex As Exception
result = False
'-- Roll the transaction back.
Try
transaction.Rollback()
Catch ex2 As Exception
Throw New Exception("Rollback failed after first exception.", ex2)
End Try
Throw New Exception("Rollback succeeded after exception.", ex)
End Try
Sorry it's some time since I did VB, but I think the syntax is correct. Using this, the calling routine should now catch the Exception (and you will have an Exception with an inner exception). You will need to examine the inner exception to find the cause.
When attempting to run a ServiceStack service, I'm getting the following error:
When debugging, the code only runs once and does not cycle through twice, I've also put breakpoints on all other functions with datareaders and none of them are being hit first and therefore managed to narrow the issue down to this one function.
Public Function GetVisitList(SiteKey As String) As List(Of VisitDetail) Implements IVisitorData.GetVisitList
Dim vlcmd As SqlClient.SqlCommand = New SqlCommand
vlcmd.CommandTimeout = 60
Try
vlcmd.Connection = Conn
vlcmd.CommandType = CommandType.StoredProcedure
vlcmd.CommandText = "GetVisitList"
vlcmd.Parameters.AddWithValue("#sitekey", SiteKey)
Dim dr As SqlDataReader = vlcmd.ExecuteReader()
Dim visitList As New List(Of VisitDetail)
While dr.Read()
Dim visit As New VisitDetail
If Not IsDBNull(dr("VKey")) Then
visit.VisitorKey = dr("VKey")
End If
If Not IsDBNull(dr("VisitIP")) Then
visit.IP = dr("VisitIP")
End If
If Not IsDBNull(dr("SiteKey")) Then
visit.SiteKey = dr("SiteKey")
End If
If Not IsDBNull(dr("Alert")) Then
visit.AlertDescription = dr("Alert")
End If
If Not IsDBNull(dr("AlertNo")) Then
visit.AlertNumber = dr("AlertNo")
End If
If Not IsDBNull(dr("VisitNo")) Then
visit.VisitNumber = dr("VisitNo")
Else
visit.VisitNumber = 0
End If
If Not IsDBNull(dr("Invited")) Then
visit.Invited = dr("Invited")
End If
If Not IsDBNull(dr("Chatted")) Then
visit.Chatted = dr("Chatted")
End If
If Not IsDBNull(dr("Prospect")) Then
visit.Prospect = dr("Prospect")
End If
If Not IsDBNull(dr("Customer")) Then
visit.Customer = dr("Customer")
End If
If Not IsDBNull(dr("HackRaised")) Then
visit.Hacker = dr("HackRaised")
End If
If Not IsDBNull(dr("Spider")) Then
visit.Spider = dr("Spider")
End If
If Not IsDBNull(dr("Cost")) Then
visit.ThisVisitCost = dr("Cost")
End If
If Not IsDBNull(dr("Revenue")) Then
visit.ThisVisitRevenue = dr("Revenue")
End If
If Not IsDBNull(dr("Visits")) Then
visit.Visits = dr("Visits")
Else
visit.Visits = 0
End If
If Not IsDBNull(dr("FirstDate")) Then
visit.FirstVisitDate = dr("FirstDate")
End If
If Not IsDBNull(dr("TotalCost")) Then
visit.TotalCost = dr("TotalCost")
End If
If Not IsDBNull(dr("TotalRevenue")) Then
visit.TotalRevenue = dr("TotalRevenue")
End If
If Not IsDBNull(dr("OperatingSystem")) Then
visit.OperatingSystem = dr("OperatingSystem")
End If
If Not IsDBNull(dr("Browser")) Then
visit.Browser = dr("Browser")
End If
If Not IsDBNull(dr("SearchEngine")) Then
visit.SearchEngine = dr("SearchEngine")
End If
If Not IsDBNull(dr("Referrer")) Then
visit.Referrer = dr("Referrer")
End If
If Not IsDBNull(dr("Keywords")) Then
visit.Keywords = dr("Keywords")
End If
If Not IsDBNull(dr("ReferrerQuery")) Then
visit.ReferrerQuery = dr("ReferrerQuery")
End If
If Not IsDBNull(dr("Name")) Then
visit.ContactName = dr("Name")
End If
If Not IsDBNull(dr("Email")) Then
visit.ContactEmail = dr("Email")
End If
If Not IsDBNull(dr("Company")) Then
visit.ContactCompany = dr("Company")
End If
If Not IsDBNull(dr("Telephone")) Then
visit.ContactTelephone = dr("Telephone")
End If
If Not IsDBNull(dr("Fax")) Then
visit.ContactFax = dr("Fax")
End If
If Not IsDBNull(dr("Street")) Then
visit.ContactStreet = dr("Street")
End If
If Not IsDBNull(dr("City")) Then
visit.ContactCity = dr("City")
visit.City = dr("City")
End If
If Not IsDBNull(dr("Zip")) Then
visit.ContactZip = dr("Zip")
End If
If Not IsDBNull(dr("Country")) Then
visit.ContactCountry = dr("Country")
visit.Country = dr("Country")
End If
If Not IsDBNull(dr("Web")) Then
visit.ContactWebSite = dr("Web")
End If
If Not IsDBNull(dr("Organization")) Then
visit.Organization = dr("Organization")
End If
If Not IsDBNull(dr("CRMID")) Then
visit.CrmID = dr("CRMID")
End If
If Not IsDBNull(dr("Notes")) Then
visit.ContactNotes = dr("Notes")
End If
If Not IsDBNull(dr("DNS")) Then
visit.DNS = dr("DNS")
End If
If Not IsDBNull(dr("Region")) Then
visit.Region = dr("Region")
End If
If Not IsDBNull(dr("FirstAlert")) Then
visit.FirstAlertDescription = dr("FirstAlert")
End If
If Not IsDBNull(dr("FirstVisitReferrer")) Then
visit.FirstReferrer = dr("FirstVisitReferrer")
End If
If Not IsDBNull(dr("ProspectTypes")) Then
visit.ProspectTypes = dr("ProspectTypes")
End If
If Not IsDBNull(dr("VisitDate")) Then
visit.SessionStarted = dr("VisitDate")
End If
If Not IsDBNull(dr("SecondsOnSite")) Then
visit.TimeOnSite = dr("SecondsOnSite")
End If
If Not IsDBNull(dr("Page")) Then
visit.Page = dr("Page")
End If
visitList.Add(visit)
dr.Close()
Conn.Close()
End While
Return visitList
Catch ex As Exception
Throw ex
End Try
End Function
The associated connection initialization is:
Public Sub Init(connectionString As String) Implements IVisitorData.Init
connString = connectionString
Conn = New SqlConnection(connectionString)
Conn.Close()
If Conn.State = ConnectionState.Closed Then
Conn.Open()
End If
End Sub
So far I've tried:
Closing the connection
Disposing the command
Closing the datareader
Deploying a check to only open the db connection if it's current state is closed
And none of these have worked. Does anybody have any idea what might be happening here? As far as I can see the datareader is only opened once then closed, but there must be something that I'm missing.
dr.Close()
Conn.Close()
End While
These should be outside the while loop. You trying to read after you have closed the connection.
End While
dr.Close()
Conn.Close()
I would put the connection, command, and datareader into using statements MSDN. It ensures the disposal of resources when the code is finished in the using block. So here is the code that I would use:
using con as new sqlconnection("connection string")
con.open()
using command as new sqlcommand("sql string", con)
'Your command code...
using rdr as sqldatareader = command.executereader()
'Your reader code...
end using
end using
end using
I think this is the best way to ensure your objects are disposed.
HTH
Wade
In addition to Kash' answer, you would be better of initializing a local instance of the SqlConnection class so it's internal to your function. The default implementation uses connection pooling on the background anyway (link), so performance wise it doesn't make a difference.
The Using statement is also very beneficial. It provides the advantage that the connection is closed and disposed automatically when it is exited. It would've avoided your current issue too.
Using conn as new SqlConnection()
conn.Open()
...
End Using
I have written a function that tells you its function itselfs as you read it:
Public Function TestConnect()
Dim verbinding As MySqlConnection
Dim errStatus As String
verbinding = New MySqlConnection()
verbinding.ConnectionString = "server=" & vardbHost & "; port=" & vardbPort & "; uid=" & vardbUser & "; pwd=" & vardbPass & "; database=" & vardbName & ";"
Try
verbinding.Open()
verbinding.Close()
errStatus = 0
Catch myerror As MySqlException
verbinding.Dispose()
verbinding.Close()
errStatus = 1
End Try
Return errStatus
End Function
Now I call this function in my main form and I thought that if I used Try and then catch the 1 or 0 then I could do something with it. (eg. Display a form with the error message) but that does not seem to work and I could not find anything on Google that applies to my problem.
Could anybody explain to me why I am so dumb and how I could better understand how to handle a returned value?
The function will be returning your value, but you need to get that assign that returned value to a variable, and then make use of it in your Calling method, eg:
Dim errStatus As Integer
errStatus = SQLHook.TestConnect()
If errStatus = 1 Then
'Show the error form
End If
Or more briefly, just test the returned value directly:
If SQLHook.TestConnect()= 1 Then
'Show the error form
End If
You should also really sort out the variable typing in your function:
Public Function TestConnect() as Boolean
Dim errStatus As Boolean
Try
errStatus = True
Catch myerror As MySqlException
errStatus = False
End Try
Return errStatus
End Function
or even more simply, don't bother with the variable:
Public Function TestConnect() as Boolean
Try
...
Return True
Catch myerror As MySqlException
...
Return False
End Try
End Function
Not entirely sure I understand the question, but do you mean something like this?
Public Function TestConnect() As Int32
...
Dim errStatus As Int32
...
Dim returnCode as Int32 = SQLHook.TestConnect()
MessageBox.show(
If(returnCode = 1, "OK", "Error"), "AppName", MessageBoxButtons.OK,
If(returnCode = 1, MessageBoxIcon.Information, MessageBoxIcon.Error)
)
I took this code from a website since VS 2010 doesn't support the timeout for the TCP connections:
Private Function ConnectWithTimeout() As Boolean
Dim ar As IAsyncResult = TCPClient.BeginConnect(IPAddress, TCPPort, Nothing, Nothing)
Dim wh As System.Threading.WaitHandle = ar.AsyncWaitHandle
Try
If Not ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2), False) Then
TCPClient.Close()
TCPClient = New System.Net.Sockets.TcpClient
Throw New TimeoutException()
End If
Catch ex As Exception
ThrowError("Timeout on connecting to " & IPAddress & " at port " & TCPPort & ".")
Return False
Finally
wh.Close()
End Try
Return True
End Function
And it works fine, but everytime, it gives me this on the debug output:
"A first chance exception of type 'System.TimeoutException' occurred in"
Even if I'm catching all the exceptions. Is there a way to get rid of this exception message as it is handled?
I've tried this:
Dim connectDone As New System.Threading.AutoResetEvent(False)
TCPClient.BeginConnect(IPAddress, TCPPort, New AsyncCallback(Sub(ar As IAsyncResult)
TCPClient.EndConnect(ar)
connectDone.Set()
End Sub), TCPClient)
'client.BeginConnect("127.0.0.1", 80, new AsyncCallback(delegate( IAsyncResult ar ) { client.EndConnect( ar ); connectDone.Set(); }), client);
If Not connectDone.WaitOne(2000) Then
Debug.WriteLine("TIMEOUT")
Return False
End If
Return True
But it gives me InvalidOperationException on the beginconnect line:
BeginConnect cannot be called while another asynchronous operation is in progress on the same Socket.
Private Function ConnectWithTimeout() As Boolean
Dim ar As IAsyncResult
Dim wh As System.Threading.WaitHandle
Try
ar = TCPClient.BeginConnect(IPAddress, TCPPort, Nothing, Nothing)
wh = ar.AsyncWaitHandle
Cath ex as Exception
'Code to catch exception
End Try
Try
If Not ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2), False) Then
TCPClient.Close()
TCPClient = New System.Net.Sockets.TcpClient
Throw New TimeoutException()
End If
Catch ex As Exception
ThrowError("Timeout on connecting to " & IPAddress & " at port " & TCPPort & ".")
Return False
Finally
wh.Close()
End Try
Return True
End Function