Data reader already open - vb.net

Have already looked questions similar to mine but none of them works for me this is my code
dbconn = New SqlConnection
dbconn.ConnectionString = ("Data Source=JENELIE\SQLEXPRESS;Initial Catalog=feeding_monitoring_system;User ID=sa;Password=Jenelie19; MultipleActiveResultSets = true")
Dim reader As SqlDataReader
Dim sda As New SqlDataAdapter
Dim ds As New DataSet()
Try
dbconn.Open()
Dim sql As String
sql = "select Count (Gender) as NumberofStudent, Gender from Student_Info Group by Gender"
dbcomm = New SqlCommand(sql, dbconn)
reader = dbcomm.ExecuteReader
sda.SelectCommand = dbcomm
sda.Fill(ds, "Student_Info")
Catch ex As SqlException
MessageBox.Show(ex.Message)
Finally
dbconn.Dispose()
End Try
Then at sda.Fill(ds, "Student_Info") an error happens

You dont use that reader at all, so i don't understand your code. You want to fill the DataSet with the DataAdapter, then this is needed (always use Using):
Dim ds As New DataSet()
Using dbconn As New SqlConnection("Data Source=JENELIE\SQLEXPRESS;Initial Catalog=feeding_monitoring_system;User ID=sa;Password=Jenelie19;MultipleActiveResultSets = true")
Dim sda = New SqlDataAdapter("select Count (Gender) as NumberofStudent, Gender from Student_Info Group by Gender", dbconn)
Try
sda.Fill(ds, "Student_Info") ' you dont need to open/close the connection
Catch ex As SqlException
MessageBox.Show(ex.Message)
End Try
End Using

I would try making sure that all disposable objects are properly disposed within this function. I recommend the Using statement to help ensure that any disposable object gets properly disposed as it goes out of scope. I believe that SqlConnection, SqlDataReader, SqlDataAdapter and DataSet are all disposable.
Edit: Although I think Tim's answer is more targeted at your problem (the SqlDataReader is unused and unnecessary), you should make sure to clean-up all your disposable objects, too. If you do use an SqlDataReader, you'll want to dispose of it before doing anything else, unless you're just trying to prove that you can have multiple result sets open at once, in which case, the lack of cleanup in multiple accesses to the same connection might be responsible (if one of them doesn't include MultipleActiveResultSets).

First off, in that situation, you do not need to use reader, you just need SQLDataAdapter.
Second, you should use Conn.Close() to close your SQL connection, rather than Conn.Dispose(). The error means that some where in your code, you opened the connection before hand, but never closed it.

Related

Best practice when executing multiple queries

When executing multiple queries what is the best practice when using Commands and DataReaders? is it best to create only one and dispose/close it before using again or create a new one everytime and dispose/close that one? For example...
Dim sqlcmd as SqlCommand
Dim sqldr as SqlDatareader
sqlcmd = new SqlCommand(Query here, connection)
sqldr = sqlcmd.ExecuteReader
'Do stuff
sqlcmd.Dispose()
sqldr.Close()
sqlcmd = new SqlCommand(Different Query here, connection)
sqlcmd.ExecuteNonQuery
'Do stuff
sqlcmd.Dispose()
'And so on
Or
Dim sqlcmd as SqlCommand = new SqlCommand(Query here, connection)
Dim sqldr as SqlDataReader = sqlcmd.ExecuteReader
'Do stuff
sqlcmd.Dispose()
sqldr.Close()
Dim anothersqlcmd as SqlCommand = new SqlCommand(Different Query here, connection)
anothersqlcmd.ExecuteNonQuery
'Do stuff
anothersqlcmd.Dispose()
'And so on
Sorry about the example, i'm aware of the using statement but my example is the same. Is it better to be just using 1 Command and DataReader or creating a new one everytime?
I think regardless the allocation is there, for readability sake I would go with option two to identify when I have a new command with different parameters
In your example, it doesn't matter. They are both the same. But in your sample 2 you have a bug by calling sqlcmd.ExecuteNonQuery.
I personally would put them in two separate method and call the method instead. Just make sure the connection object is open only when needed and close is right away when not needed.
This is just what I do, not necessarily Best Practices but I am very careful to close my connections and dispose of my objects.
cn.Open()
If Mode = "Add" Then
cmd.CommandText = "InsertVendor"
RetVal = cmd.ExecuteNonQuery
Else 'Update
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = itgID
cmd.CommandText = "UpdateVendors"
RetVal = cmd.ExecuteNonQuery
End If
cn.Close()
cmd.Dispose()
Here, I used one command object but tailored it for 2 different operations. To get everything cleaned up I use Try..Catch..Finally
Finally
If Not IsNothing(cmd) Then
cmd.Dispose()
End If
If cn.State = ConnectionState.Open Then
cn.Close()
End If
End Try
Then check on the state of my objects there. There should never be an exception in a Finally block. I do use the same connection object throughout my DataAccess Class. Be careful of the DataReader; don't close your connection until it has finished its work.

Visual Basic, Copying Success but does not Insert data into SQL TABLE

I have some problems here. I need help.
Recently, I have created a local database called stock.mdf and the application will be getting all the data from the hosting MySQL database into this local SQL Server database.
I am using sqlBulkCopy to inserting all the data. I have tried to view it after inserting. But when I close my application, I head back to check the table data. It does not inserted. Why is that?
Here is my code:
Here will be retrieving the data from the hosting
Dim connStr As String = "server=xxxx;user=xxx;database=xxx;password=xxxx;"
Dim conn As New MySqlConnection(connStr)
Dim cmd As New MySqlCommand
Dim Adapter As New MySqlDataAdapter
Dim StockData As New DataTable
Try
Dim SQL As String = "SELECT * FROM stock"
Console.WriteLine("Connecting to MYSQL.....")
conn.Open()
cmd.Connection = conn
cmd.CommandText = SQL
Adapter.SelectCommand = cmd
Adapter.Fill(StockData)
' StockViewGrid.DataSource = StockData
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
conn.Close()
Console.Write("Done")
End Try
This will be the places where sqlBulkCopy working:
As well, I am trying to view from the stock table.
Dim Local_connectionStr As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|stock.mdf;Integrated Security=True"
Dim Local_conn As New SqlConnection(Local_connectionStr)
Dim Local_cmd As New SqlCommand
Dim Local_Adapter As New SqlDataAdapter
Dim Local_StockData As New DataTable
Try
Using sqlBulkCopy As New SqlBulkCopy(Local_conn)
'Set the database table name
sqlBulkCopy.DestinationTableName = "stock"
'[OPTIONAL]: Map the DataTable columns with that of the database table
sqlBulkCopy.ColumnMappings.Add("stockId", "stockId")
sqlBulkCopy.ColumnMappings.Add("id_android", "id_android")
sqlBulkCopy.ColumnMappings.Add("itemCode", "itemCode")
sqlBulkCopy.ColumnMappings.Add("quantity", "quantity")
Local_conn.Open()
sqlBulkCopy.WriteToServer(StockData)
Local_conn.Close()
End Using
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
Local_conn.Close()
Console.Write("Done")
End Try
Try
Dim SQL As String = "SELECT * FROM stock"
Console.WriteLine("Connecting to MYSQL.....")
Local_conn.Open()
Local_cmd.Connection = Local_conn
Local_cmd.CommandText = SQL
Local_Adapter.SelectCommand = Local_cmd
Local_Adapter.Fill(Local_StockData)
StockViewGrid.DataSource = Local_StockData
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
Local_conn.Close()
Console.Write("Done")
End Try
Since I can't comment (not enough points) I will put my thoughts here. Can you check that you got the expected data with a
Console.WriteLine(StockData.Rows.Count.ToString)
Console.ReadLine()
Also, your destination table doesn't have a PK that is auto increment, does it?
Sorry about the comment as an answer. (Untested code)
Unfortunately your code extracts are lacking headers etc, so are not complete, and I cannot be absolutely certain, BUT in your retrieving routine you seem to be declaring StockData as a local variable. This means that, although this may well be being filled with the data from MySQL, it is immediately discarded on exiting from this routine. Therefore the StockData variable in the sqlBulkCopy routine will be empty, and therefore will insert nothing. You need to fix your scope and make sure that the StockData read from MySQL is the same StockData used in SqlBulkCopy.

OleDbCommand unclosed Datareader Error

I get a System.InvalidOperationException with the additional Info saying that there is an unclosed Datareader in this line.
MyCmd.ExecuteNonQuery()
MyCmd is a Private variable accessible for all subs and is declared as
MyCmd = New OleDb.OleDbCommand()
MyCmd.CommandText = "Insert Into Netzwerkverwaltung(NSub, Nip, Npc, Nuser, Pherst, Pser, Pmod, Pcpu, Phdd, Pram, Pkauf, Sos, Sosoem, Sosopen, Sfunk, Soffice, Sofficeoem, Sofficeopen, Anmerkung) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"
MyCmd.Connection = MyCon
After this the parameters are added.
I use MyCon in a Sub before with a Datareader but the Datareader is closed when I debug it but it still doesn't work.
Dim myDR As OleDb.OleDbDataReader
MyCmd = New OleDb.OleDbCommand("SELECT * FROM Netzwerkverwaltung WHERE ID=?", MyCon)
MyCmd.Parameters.Add(New System.Data.OleDb.OleDbParameter("ID", System.Data.OleDb.OleDbType.Integer))
MyCmd.Parameters("ID").Value = Request("ID")
If MyCon.State = ConnectionState.Closed Then
MyCon.Open()
End If
myDR = MyCmd.ExecuteReader()
There I implement the Datareader and close it later on, and it is closed, I double checked that.
This code worked perfectly fine in VS2010 BTW. And I am working with VS2015 right now.
If you're getting an error message telling you that there is a data reader open on that connection then there almost certainly is. This is why you should always use Using blocks for short-lived, disposable objects, e.g.
Using myDataReader = myCommand.ExecuteReader()
'Use myDataReader here.'
End Using
The reader will be implicitly closed at the End Using line so you can't accidentally leave it open. Depending on specifics, you should probably be doing the same thing with your connection too.

SqlDataReader vb.net keep connection open

I am using this code to get data:
Dim connetionString As String
Dim connection As SqlConnection
Dim sqlq As String
sqlq = "select top 1 * from table1 where smth"
Dim ds As New DataSet
connetionString = "Data Source=db;Initial Catalog=ic;User ID=id;Password=pass"
connection = New SqlConnection(connetionString)
Try
Using connection
Dim command As SqlCommand = New SqlCommand(sqlq, connection)
connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader()
If reader.HasRows Then
Do While reader.Read()
x = reader.GetString(5)
Loop
End If
reader.Close()
End Using
Catch ex As Exception
End Try
This type of connection (with different sqlq [query]) I use a lot in diffenrent functions and every time I close the connection. I want to optimize it so it would take less time to get data. How do I do that?
It is best practise to always dispose/close a connection as soon as you're finished with it. Actually the connection-pool will not close the underlying physical connection but only flag this connection as reusable if it is closed. So if you don't close a connection it cannot be reused, hence the pool needs to create a new physical connection which is very expensive.
So only some minor improvements:
Const sql = "select top 1 * from table1 where smth"
Dim table As New DataTable()
Using con = New SqlConnection("Data Source=db;Init ....")
Using command = New SqlCommand(sql, con)
Using da= New SqlDataAdapter(command)
da.Fill(table)
End Using
End Using
End Using
You should use Using for any object implementing IDisposable. You should not use an empty Catch block.
Use connection pooling instead.
By default as long as the connection string is the same, connections will be taken from the same connection pool.
Shortly connection pool keeps not needed connections open, and return that connections on the next request, so you don't need to think about the time it take to open connection.
Keeping connections open for longer than you needed is bad idea, because it costs resources, and in general some servers can accept limited connections.

VB.NET - Multiple SQLDataReader's

I develop a lot in ASP.NET and I know that you can only open one SQLDataReader for each SQLConnection. However, this does not appear to be the case in VB.NET (form application) i.e. I have opened multiple SQLDataReaders for one connection object. Is this allowed in VB.NET?
If there is not an obvious answer to this then I will post some code.
Here is some code:
Public Function CheckActiveReviews()
Dim objCon As SqlConnection
Dim objCommand As SqlCommand, objCommand2 As SqlCommand
Dim objDR As SqlDataReader, objDR2 As SqlDataReader
Try
objCon = New SqlConnection("Data Source=TestDatabase;Initial Catalog=TestTable;User ID=TestUser;Password=TestPassword;MultipleActiveResultSets=True")
objCommand = New SqlCommand
objCommand.Connection = objCon
objCommand2 = New SqlCommand
objCommand2.Connection = objCon
objCon.Open()
objCommand.CommandText = "SELECT ID FROM Person WHERE PersonID > 1000"
objDR = objCommand.ExecuteReader()
Do While objDR.Read
objCommand2.CommandText = "SELECT * FROM Sport WHERE PersonID = #PersonID "
objCommand2.Parameters.AddWithValue("#PersonID", objDR("ID"))
objDR2 = objCommand2.ExecuteReader
Loop
Catch ex As Exception
End Try
End Function
You can use multiple data readers if you use MARS - Multiple Active Result Sets - but I wouldn't advise that unless you really need it.
Instead, I'd suggest creating a new SqlConnection object each time you need it - use it for as short a period as you can, then dispose of it (use a Using statement to do this for you). The connection pool will take care of the efficiency in terms of reusing "physical" network connections where possible. That way you don't need to worry about whether the SqlConnection is already open etc - you just always follow the same "create, open, use, dispose" pattern every time.