So here is my issue:
Currently I am trying to make a report that will show 1st and 2nd shifts, by multiple days...
So if they select the range 6/02 - 6/04, I am running a query 3 times... once for 6/02, 6/03, and 6/04... Also they can select shift, so it would be those dates, but 4:30AM-4:30PM for 1st shift....
Currently I have a error, when trying to put my queries/calls inside the for loop... I calculate the difference of the two dates and set them up fine, its just my connection string gives me the error:
If the image is not easy to see here is a text description of the error:
Server Error in '/mfgx_test' Application.
Fill: SelectCommand.Connection property has not been initialized.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Fill:
SelectCommand.Connection property has not been initialized.
Source Error:
Line 623: Dim dsTop1 As New DataSet Line 624: Dim daTop1
As New SqlDataAdapter(strSql, myCn1) Line 625:
daTop1.Fill(dsTop1) Line 626: Line 627: myCn1.Close()
Source File: C:\inetpub\wwwroot\mfgx_test\defectsbyround.aspx.vb
Line: 625
Which leads me to beleive that something is wrong with my connection string being outside of my for loop... My code is as follows (Although a bit cleaned up so it is easier to read):
Dim myCn1 As New SqlConnection
myCn1.ConnectionString = "server=Blah;database=Blah;user id=Blah;password=Blah"
myCn1.Open()
For i = 0 To Session("DaysDiff")
strSql = "Blah.Blah"
Dim dsTop1 As New DataSet
Dim daTop1 As New SqlDataAdapter(strSql, myCn1)
daTop1.Fill(dsTop1)
myCn1.Close()
myCn1 = Nothing
If dsTop1.Tables(0).Rows.Count > 0 Then
spitout2(dsTop1)
End If
txtStartdate.Text = DateAdd("d",1,txtStartdate.Text)
txtEnddate.Text = DateAdd("d",1,txtEnddate.Text)
Next
That's because you are closing the connection inside your loop and so for next iteration there is no open connection present and hence the exception (see pointed below)
myCn1.Close()
myCn1 = Nothing
You should declare the Dataset and tableadapter as well out side the loop context. Your code should somewhat look like below
Dim myCn1 As New SqlConnection
myCn1.ConnectionString = "server=Blah;database=Blah;user id=Blah; password=Blah"
myCn1.Open()
Dim dsTop1 As New DataSet
Dim daTop1
For i = 0 To Session("DaysDiff")
strSql = "Blah.Blah"
daTop1 As New SqlDataAdapter(strSql, myCn1)
daTop1.Fill(dsTop1)
.......
Next
myCn1.Close()
myCn1 = Nothing
Assuming you want to reuse the connection inside the loop, release the connection automatically with a Using statement outside the for loop
Using myCn1 As New SqlConnection("server=Blah;database=Blah;user id=Blah;password=Blah")
myCn1.Open()
For i = 0 To Session("DaysDiff")
strSql = "Blah.Blah"
Dim dsTop1 As New DataSet
Dim daTop1 As New SqlDataAdapter(strSql, myCn1)
daTop1.Fill(dsTop1)
If dsTop1.Tables(0).Rows.Count > 0 Then
spitout2(dsTop1)
End If
txtStartdate.Text = DateAdd("d",1,txtStartdate.Text)
txtEnddate.Text = DateAdd("d",1,txtEnddate.Text)
Next
End Using
When End Using is reached, SqlConnection.Dispose() will be called, releasing connection resources.
Related
Hello stack overflow residents! this is my first post and i'm hoping to receive some help.
I've searched but because I'm still very new, i was not able to full find/understand my answer.
I keep encountering this error:
Message: Conversion from string "" to type 'Date' is not valid. File:
~/reports/pendingshipments.aspx Function: btnExportXls_Click Stack
Trace: at
Microsoft.VisualBasic.CompilerServices.Conversions.ToDate(String
Value) at reports_default.btnExportXls_Click(Object sender, EventArgs
e) in C:\Users\jet.jones\Documents\ERIRoot\ERITitan\ERITitan.ssa\Web
Application\reports\pendingshipments.aspx.vb:line 75
Here is my code:
on App_code
**Public Function Reports_PendingShipments(ByVal intClientID As Integer, ByVal strMinDate As Date?, ByVal strMaxDate As Date?, ByVal xmlSiteID As String) As DataTable
'=================================================================================
' Author: Jet Jones
' Create date: 2013.05.28
' Description: Returns a data table with pending shipments for the sites specified
'=================================================================================
Dim objConn As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("Titan").ToString)
Dim cmdGet As New SqlCommand("spReports_PendingShipments", objConn)
Dim parClientID As New SqlParameter("#ClientID", SqlDbType.Int)
Dim parMinDate As New SqlParameter("#MaxDate", IIf(Not strMinDate.HasValue, DBNull.Value, strMinDate))
Dim parMaxDate As New SqlParameter("#MaxDate", IIf(Not strMaxDate.HasValue, DBNull.Value, strMaxDate))
Dim parSiteID As New SqlParameter("#Sites", SqlDbType.Xml)
Dim objAdapter As New SqlDataAdapter(cmdGet)
Dim objTable As New DataTable
parClientID.Value = intClientID
parMinDate.Value = strMinDate
parMaxDate.Value = strMaxDate
parSiteID.Value = xmlSiteID
'set up the command object
cmdGet.Connection = objConn
cmdGet.CommandType = CommandType.StoredProcedure
'add the parameters
cmdGet.Parameters.Add(parClientID)
cmdGet.Parameters.Add(parMinDate)
cmdGet.Parameters.Add(parMaxDate)
cmdGet.Parameters.Add(parSiteID)
'open the connection
objConn.Open()
'execute the query and fill the data table
objAdapter.Fill(objTable)
'return the data table
Reports_PendingShipments = objTable
'clean up
objConn.Close()
objConn = Nothing
End Function**
my aspx.vb page calls this function this way (Get the values from the query):
objTable = Reports_PendingShipments(ucClientSearch.Value,
txtMinDate.Text, txtMaxDate.Text, strSites)
I'm passing the variable strSites because the website permissions allow for users to have access to one or more site locations, and if a report is run and the user selects "All Sites" from the dropdown, I only want to send the sites they have permissions to via XML.
If I'm missing any information please let me know!
anyone's prompt response is so greatly appreciated.
The problem is that your code is expecting empty dates to be NULL, it doesn't check for empty strings. You need something like this:
if len(strMinDate)=0 then
strMinDate = "01/01/1980"
end
Not sure what you want to default the minimum date to, but you need to add code similar to the IF statement above
Be sure to add this code prior to using the variable a few lines later...
First of all, you adding MaxDate parameter twice:
Dim parMinDate As New SqlParameter("#MaxDate", IIf(Not strMinDate.HasValue, DBNull.Value, strMinDate))
Dim parMaxDate As New SqlParameter("#MaxDate", IIf(Not strMaxDate.HasValue, DBNull.Value, strMaxDate))
And moreover, then you setting parameters values wuthout check for HasValue:
parMinDate.Value = strMinDate
parMaxDate.Value = strMaxDate
Remove these lines and fix min date parameter name
currently I have a serious problem with one of my web applications which runs into a Timeout Exception around half a dozen times a day.
Error: "The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached".
After a lot of googling I found out that the problem has something to do with unclosed connections. So I checked all functions that access the database in any way until I stumbled upon this one:
Private Sub getOrgas(ByVal orgID As String)
Dim Id = orgID
orgColl.Add(Id)
While (Not IsNothing(Id))
Dim conn = Database.DbWrapper.GetConnection(1, Integration.Mandanten.DatabaseType.AddonSQL)
Dim paras As New HashSet(Of System.Data.Common.DbParameter)
Dim orgatmp As String
paras.Add(New SqlClient.SqlParameter("#Id", orgID))
Dim dr = Database.DbWrapper.GetDataReaderFromStoredProcedure("stp_Orgas_Get", paras, conn)
While dr.Read
If Not valueInColl(CStr(dr(0))) Then
orgatmp = dr(0).ToString
orgColl.Add(orgatmp)
getOrgas(orgatmp)
End If
End While
dr.Close()
conn.Close()
Id = Nothing
End While
End Sub
As you can see this function executes a stored procedure and runs the results through a while loop where it calls the function again if a specific condition -valueInColl-. Now in that way it is possible that there are 20 or more open connections. It has nothing to do with the timeout-value which is set via the GetDataReaderFromStoredProcedure to 600 which actually should be enough. To be sure I doubled the value and will roll it out this evening. I'll see whether that helped within the next day then.
I believe the problem is that there are too many open connections at the same time, because of the recursive function, but I have no clue how to solve this.
I couldn't find anything as to how to edit the max connections. I'm not even entirely sure where have to set it. Is it the IIS, the DB itself or is it a programming-parameter (VB.net/ASP.NET).
Would be nice if you guys could help me out here.
[EDIT]
Ok, somebody had the idea to reuse the connection variable, but this won't work as the datareader is still running. As long as it is not closed I can't reuse the connection in any way and I can't close the datareader, because I might lose data if I do so. The while-loop for dr.read hasn't ended, yet ..
On the other hand I deleted the (pretty much useless) outer while and used an If-clause in exchange:
Private Sub getOrgas(ByVal orgID As String, ByVal con As DbConnection)
Dim Id = orgID
Dim conn As DbConnection
Dim tmpOrga As String
orgColl.Add(Id)
If Not IsNothing(Id) Then
If IsNothing(con) Then
conn = Database.DbWrapper.GetConnection(1, Integration.Mandanten.DatabaseType.AddonSQL)
Else
conn = con
End If
Dim paras As New HashSet(Of System.Data.Common.DbParameter)
paras.Add(New SqlClient.SqlParameter("#Id", orgID))
Dim dr = Database.DbWrapper.GetDataReaderFromStoredProcedure("stp_Orgas_Get", paras, conn)
While dr.Read
If Not valueInColl(CStr(dr(0))) Then
tmpOrga = dr(0).ToString
orgColl.Add(tmpOrga)
getOrgas(tmpOrga, conn)
End If
End While
dr.close()
conn.Close()
Id = Nothing
End If
End Sub
Is there any reason you cannot refactor things so that each recursion uses the same db connection?
I am not a VB coder but I would tackle it as follows
Change getOrgas() to take a connection parameter defaulting to 'nothing'.
Change the Dim conn line to if IsNothing(connParameter) conn = GetConnection() else conn := connParameter;
Change your recursion line to getOrgas(orgatmp, conn);
Test the F%%%% out of it.
I have just noticed the outer While Loop. Is it there just to confuse you ? How many times will it execute ? ...
I did wonder about the datareader -
try this - I see that your datareader needs to close before you recurse, so close it.
in pseudocode -
dim locallist = new list();
while dr.read
{
LocalList.Add dr.thing;
}
dr.close;
foreach(thing in locallist)
{
if Not ValueInColl(thing) Then
CallYourFunctionTRecursively()
end if;
}
Are you with me ?
If you are trying to put together all the members of a family then it depends which database system you are using how it is done, but look up 'Heirarchical queries' in your documentation.
I am currently working on an asp.net web page with a GridView displaying a table from a database. This GridView has 4 DropDownLists that will be used to filter the data shown on the GridView. When the page loads 4 Sub routines are run, each one connecting to the database with a select statement to fill the DropDownList with relevant filter headings.
Initially, I had one connection with a loop that populated all of the drop downs but these contained duplicates. I then split the filling of each DDL so that the select statements could contain DISTINCT.
I would like (and am sure there is a way here) to be able to populate all of the DDLs with data from one connection.
Code for one connection:
Protected Sub FillDepDDL()
Dim conn As New SqlConnection()
conn.ConnectionString = WebConfigurationManager.ConnectionStrings("TestDBConnectionString").ConnectionString
Dim connection As New SqlConnection(conn.ConnectionString)
connection.Open()
Const FillAllQS As String = "SELECT DISTINCT [Department] FROM [Employees]"
Dim command As New SqlCommand(FillAllQS, connection)
Dim reader As SqlDataReader = command.ExecuteReader()
Dim sel As New ListItem
sel.Text = "Please Select"
sel.Value = "*"
DDLDepartment.Items.Add(sel)
While reader.Read
Dim Deplist As New ListItem()
Deplist.Value = reader("Department")
Deplist.Text = reader("Department")
DDLDepartment.Items.Add(Deplist)
End While
reader.Close()
conn.Close()
End Sub
The other 3 column names: FirstName > DDLFN, LastName > DDLLN, Wage > DDLWag.
This is only a test DB and the princibles learned here will be applied to a larger live project.
I'm sure some guru will be able to work this out easily but I just can't get my head round it even after hours of searching.
Thanks in advance.
I'm adding this in as answer because I cannot format it in a comment, but this doesn't answer the original question of how to write the sql to return all three distinct result sets. Instead, it answers how to rewrite the code you have above so that connections are properly disposed of in case of an exception.
Protected Sub FillDepDDL()
Dim Deplist As ListItem
Dim sel As New ListItem
sel.Text = "Please Select"
sel.Value = "*"
DDLDepartment.Items.Add(sel)
Using conn As New SqlConnection(WebConfigurationManager.ConnecitonString("TestDBConnectionString").ConnectionString)
Using cmd As New SqlCommand("SELECT DISTINCT [Department] FROM [Employees]", conn)
conn.Open()
Using reader = cmd.ExecuteReader()
While reader.Read
Deplist = New ListItem()
Deplist.Value = reader("Department")
Deplist.Text = reader("Department")
DDLDepartment.Items.Add(Deplist)
End While
End Using
End Using
End Using
End Sub
I don't see any reason for you to try to return all three results in a single query. That will just make your code unnecessarily complicated just to save a millisecond or two. Connection pooling handles the creation of connections on the database server for you, so opening a new connection in your code is very fast.
I have the below mentioned code in a seperate class file for establishing connection and carry out DB transactions. I have an issue where multiple connections being opened which sometime exceed the connection pool. When I stepped through the code I found that there are codes which call ConnectDB() in a loop without calling DisconnectDB(). But I expected that the condition OraConn.State = ConnectionState.Closed should handle the situation. Somehow the condition is always satisfied hence openning another set of connection. Can you suggest where am I going wrong and also what best practice can be adopted here?
Public Class Connection
Dim Str_conn As String = "Data Source=...; User=...; password=...; Min Pool Size=10; Max Pool Size=500;"
Public OraConn As OracleConnection
Dim cmd As OracleCommand
Dim dr As OracleDataReader
Dim data_adapt As OracleDataAdapter
Dim dt As DataTable
Dim ds As DataSet
Public Sub ConnectDB()
OraConn = New OracleConnection(Str_conn)
If OraConn.State = ConnectionState.Closed Then
OraConn.Open()
End If
End Sub
Public Sub DisconnectDB()
If OraConn.State = ConnectionState.Open Then
OraConn.Close()
End If
End Sub
Public Function get_dataset(ByVal query As String, ByRef ds As DataSet) As DataSet
data_adapt = New OracleDataAdapter(query, OraConn)
data_adapt.Fill(ds)
Return ds
End Function
Public Function get_datareader(ByVal query As String) As OracleDataReader
cmd = New OracleCommand(query, OraConn)
dr = cmd.ExecuteReader()
Return dr
End Function
Public Sub UpdateDB(ByVal query As String)
cmd = New OracleCommand(query, OraConn)
cmd.ExecuteNonQuery()
cmd.Dispose()
End Sub
The class is refered in other classes or directly in the aspx.vb pages like this.
Public Function InsertData(ByVal var1 As String, ByVal var2 As String) As Integer
conn.ConnectDB()
Dim qryInsert As String
qryInsert = " INSERT INTO TABLE VALUES ('" & var1 & "', "
qryInsert = qryInsert & var2 & "')"
Try
conn.UpdateDB(qryInsert)
Catch ex As OracleException
If ex.Code = 1 Then
updData(var1, var2)
ElseIf ex.Code = 2091 Then
msgprompt("Duplicate Unique Key!", "Warning")
End If
Finally
conn.DisconnectDB()
End Try
Return count
End Function
The connection is again opened in function updData(). While I understand that it has to be closed correctly but keeping tab on every developer is not possible. Hence I want to control it directly from the connection class by using the same connection but the condition If OraConn.State = ConnectionState.Closed is not helping.
UPDATE
I have put the code in UpdateDB under a Using block and removed call to ConnectDB and DisconnectDB from function like InsertData(...). It seems that the issue has been resolved. But I would like to know in case of exception will the connection remain open? and also OraConn is a public variable defined outside Using block so will it be disposed of by the GC?
Public Sub UpdateDB(ByVal query As String)
Using OraConn = New OracleConnection(Str_conn)
cmd = New OracleCommand(query, OraConn)
Try
OraConn.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
Throw
Finally
cmd.Dispose()
End Try
End Using
End Sub
You must close all the connections as soon as you are done with it, no matter what.
Suggestion:
The best practice for closing the connection is to do it in finally block. So that even if there is any error, catch it (log it if required) in catch block, and then connection will get close in finally block.
UPDATE
You can put one private static counter in your Connection class. When ever ConnectDB() is called you increment this counter and decrement it in every DisconnectDB(). Now in ConnectDB() you check the value of counter, if it exceeds a minimum threshold you throw error, by doing this way; you can come to know idle connection present in your code and refactor it. On production keep this threshold value high or ignore it in code.
i am making a website for trading, with trading feeds coming from a source in an excel sheet. I have to show data from the excel sheet in a gridview. When i make connection it will fail due to rapidly changing data; each cell in the sheet changes value 1-3 times per second. I am using an Ajax Timer of interval 100. Here is my code:
Public Function RetrieveExcelData(ByVal excelSheetName As String, ByVal sheetNumber As Integer) As DataSet
Dim objConn As OleDbConnection = Nothing
Dim dt As System.Data.DataTable = Nothing
Try
' Connection String.
Dim connString As [String] = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=C:\Users\Vishal\Desktop\TESTING COLOURfor web1.xls;Extended Properties=Excel 8.0;"
' Create connection object by using the preceding connection string.
objConn = New OleDbConnection(connString)
' Open connection with the database.
objConn.Open()
' Get the data table containg the schema guid.
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
If dt Is Nothing Then
Return Nothing
End If
Dim excelSheets As [String]() = New [String](dt.Rows.Count - 1) {}
Dim i As Integer = 0
' Add the sheet name to the string array.
For Each row As DataRow In dt.Rows
excelSheets(i) = row("TABLE_NAME").ToString()
i += 1
If i = sheetNumber Then
Exit For
End If
Next
Dim excelCommand As New OleDbCommand("Select * from [" + excelSheets(sheetNumber - 1) & "]", objConn)
Dim excelAdapter As New OleDbDataAdapter(excelCommand)
Dim excelDataSet As New DataSet()
excelAdapter.Fill(excelDataSet)
Return excelDataSet
Catch ex As OleDbException
Throw ex
Catch ex As Exception
Throw ex
Finally
' Clean up.
If objConn IsNot Nothing Then
objConn.Close()
objConn.Dispose()
End If
If dt IsNot Nothing Then
dt.Dispose()
End If
End Try
End Function
To be honest - I cannot see how it can work. You are trying to use Excel spreadsheet as a database to store and retrieve data in real-time, for which Excel was never intended or designed.
You have mentioned that the Excel gets data several times per second. What is the source of data? RTD component? Bloomberg API? I would try to avoid the middle step of storing data in a spreadsheet.