Visual Studio Vb.net loaded dataset from oracle query missing or replacing first row of data - vb.net

I have a vb.net application program that is suppose to query a oracle/labdaq database and load the dataset into a datatable. For some reason the query works fine and there is no exception thrown, however, when I load the data it seems to be missing the first row. I first noticed the issue when I did a query for a single row and it returned zero rows when I checked the datatable's row amount during debugging. I then compared all my data sets to a data miner application straight from the oracle source and i seems to always be missing one, the first, row of data when I use the application.
here is the code... I changed the query string to something else to maintain company privacy
Private Sub CaqOnSQL(strFileDirect As String)
Try
Dim connString As String = ConfigurationManager.ConnectionStrings("CA_Requisition_Attachments.Internal.ConnectionString").ConnectionString
Dim conn As New OracleConnection With {
.ConnectionString = connString
}
Dim strQuerySQL As String = "SELECT * FROM REQUISITIONS " &
"WHERE DATE BETWEEN TO_DATE('12/10/2020','MM/dd/yyyy') AND " &
"TO_DATE('12/14/2020','MM/dd/yyyy') " &
"ORDER BY ID"
conn.Open()
Dim Cmd As New OracleCommand(strQuerySQL, conn) With {
.CommandType = CommandType.Text
}
Dim dr As OracleDataReader = Cmd.ExecuteReader()
dr.read()
Dim dt As New DataTable
dt.TableName = "RESULTS"
dt.Load(dr)
ExcelFileCreation(dt, strFileDirect)

You should remove the line:
dr.read()
The call to Read is what is causing you to skip the first row, when combined with the DataTable Load method.
In addition, I have taken the liberty to make some additional changes to your code for the purposes of Good Practice. When using Database objects like Connection and Command, you should wrap them in Using blocks to ensure the resources are released as soon as possible.
Dim dt As New DataTable()
dt.TableName = "RESULTS"
Using conn As New OracleConnection(connString)
conn.Open()
Dim strQuerySQL As String = "SELECT * FROM REQUISITIONS " &
"WHERE DATE BETWEEN TO_DATE('12/10/2020','MM/dd/yyyy') AND " &
"TO_DATE('12/14/2020','MM/dd/yyyy') " &
"ORDER BY ID"
Using command = New OracleCommand(strQuerySQL , conn)
Using dataReader = command.ExecuteReader()
dt.Load(dataReader)
End Using
End Using
End Using
Note: Be wary of Using blocks when using a DataReaderas you may find the connection is closed when you don't want it to be. In this case, the DataReader is used entirely within this function and is safe to use.

Related

Reading from a database and using an if statement

The program currently reads from the database, but what I am trying to do is try to get the program to read from the database and if the field is empty then output "TBC" and if not then it will show the grade. I'm unsure of how to check what dr.Read is and use an if statement with it.
Sub GradeResult()
Dim dr As OleDbDataReader
Dim cm As New OleDbCommand
Dim cn As New OleDbConnection
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=login.accdb"
cn.Open()
cm.CommandText = "SELECT ArGrade FROM loginDetails WHERE UserName = '" & username & "'"
cm.Connection = cn
dr = cm.ExecuteReader
dr.Read()
Label6.Text = dr.Item("ArGrade")
End Sub
Instead of using an if statement, when the user registers, the program writes TBC into the field.
dr is an instance of the OleDbDataReader class, and Read is one public method of this class. You need to call it in order to start reading the results after a query is executed against the database.
From the OleDbDataReader.Read documentation page:
Advances the OleDbDataReader to the next record.
You need to call it at least once, to get some results.
Returns
Boolean
true if there are more rows; otherwise, false.
Use it to check if you have any results at all or more results as one.
The default position of the OleDbDataReader is before the first record. Therefore, you must call Read to start accessing any data.
In your case you can check if there is any result like this:
Label6.Text = "TBC" ' standard value is no value found
if dr.Read() then ' DB contains any rows
dim arGrade = dr.Item("ArGrage")
if not IsDbNull(arGrade) then ' and the ArGrade has a value
Label6.Text = arGrade
end if
end if
And don't forget to close the reader with dr.Close.

Adding SQL Parameter fails

This is a new concept for me and I can't quite see what's causing the error
I'm attempting to populate a datagridview control from a single field in an Access database (from a combo and Text box source).
Using literals works, but not with the parameter.
Dim conn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Backend & ";Persist Security Info=False;")
Dim command As New OleDbCommand("Select Year from tblTest ", conn)
Dim criteria As New List(Of String)
If Not cboYear.Text = String.Empty Then
criteria.Add("Year = #Year")
command.Parameters.AddWithValue("#Year", cboYear.Text)
End If
If criteria.Count > 0 Then
command.CommandText &= " WHERE " & String.Join(" AND ", criteria)
End If
Dim UserQuery As New OleDbDataAdapter(command.CommandText, conn)
Dim UserRet As New DataTable
UserQuery.Fill(UserRet)
With frmDGV.DataGridView2
.DataSource = UserRet
End With
frmDGV.DataGridView2.Visible = True
frmDGV.Show()
Trying to Fill the datatable shows exception 'No value given for one or more required parameters.'
The value of command.CommandText at that point is "Select Year from tblTest WHERE Year = #Year"
Your instance of OleDbDataAdapter was created using two parameters query text and connection.
Dim UserQuery As New OleDbDataAdapter(command.CommandText, conn)
In this case DataAdapter doesn't know about parameters at all.
Instead use constructor with paremeter of type OleDbCommand.
Dim UserQuery As New OleDbDataAdapter(command)
In your code instance of OleDbCommand already associated with connection

VB.net- Data type mismatch in criteria expression

I am trying to add the vote count after the selected user from the ddl.
I Don't see what I did wrong.
Dim str As String
str = "update [vote] SET [voteweight] = [voteweight]+1 where [userID] = 'DropDownList4.Selectedvalue'"
Dim Conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;; data source=" & Server.MapPath("App_Data/final.mdb"))
Dim cmd As New OleDbCommand(str, Conn)
Conn.Open()
cmd.ExecuteNonQuery()
Conn.Close()
The correct way to pass a value to an sql command is through a parameterized query. Otherwise the errors that could be embedded in your string are very numerous and subtle.
In your code, the single quotes around the control value, transform everything in a literal string and, of course, the UserID field is a numeric field that cannot be compared against a string
if DropDownList4.Selectedvalue = Nothing then
Return
End If
Dim str = "update [vote] SET [voteweight] = [voteweight]+1 " & _
"where [userID] = #userid"
Using Conn = New OleDbConnection(.....)
Using cmd As New OleDbCommand(str, Conn)
Conn.Open()
cmd.Parameters.Add("#userid", OleDbType.Int).Value = Convert.ToInt32(DropDownList4.Selectedvalue)
cmd.ExecuteNonQuery()
End Using
End Using
Other things to keep present are:
Using Statement around disposable object like the connection and the command (thus avoiding the possibility to leak resources if an exceptions triggers and you forget to dispose them)
A check around the SelectedValue for null is always a good measure. Sometimes your control could loose the Selection and you should be absolutely sure that there is no way to enter this code with a SelectedValue = Nothing.

How do I assign the results of an SQL query to multiple variables in VB.NET?

This is my first attempt at writing a program that accesses a database from scratch, rather than simply modifying my company's existing programs. It's also my first time using VB.Net 2010, as our other programs are written in VB6 and VB.NET 2003. We're using SQL Server 2000 but should be upgrading to 2008 soon, if that's relevant.
I can successfully connect to the database and pull data via query and assign, for instance, the results to a combobox, such as here:
Private Sub PopulateCustomers()
Dim conn As New SqlConnection()
Dim SQLQuery As New SqlCommand
Dim daCustomers As New SqlDataAdapter
Dim dsCustomers As New DataSet
conn = GetConnect()
Try
SQLQuery = conn.CreateCommand
SQLQuery.CommandText = "SELECT Customer_Name, Customer_ID FROM Customer_Information ORDER BY Customer_Name"
daCustomers.SelectCommand = SQLQuery
daCustomers.Fill(dsCustomers, "Customer_Information")
With cboCustomer
.DataSource = dsCustomers.Tables("Customer_Information")
.DisplayMember = "Customer_Name"
.ValueMember = "Customer_ID"
.SelectedIndex = -1
End With
Catch ex As Exception
MsgBox("Error: " & ex.Source & ": " & ex.Message, MsgBoxStyle.OkOnly, "Connection Error !!")
End Try
conn.Close()
End Sub
I also have no problem executing a query that pulls a single field and assigns it to a variable using ExecuteScalar. What I haven't managed to figure out how to do (and can't seem to hit upon the right combination of search terms to find it elsewhere) is how to execute a query that will return a single row and then set various fields within that row to individual variables.
In case it's relevant, here is the GetConnect function referenced in the above code:
Public Function GetConnect()
conn = New SqlConnection("Data Source=<SERVERNAME>;Initial Catalog=<DBNAME>;User Id=" & Username & ";Password=" & Password & ";")
Return conn
End Function
How do I execute a query so as to assign each field of the returned row to individual variables?
You probably want to take a look at the SqlDataReader:
Using con As SqlConnection = GetConnect()
con.Open()
Using cmd As New SqlCommand("Stored Procedure Name", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#param", SqlDbType.Int)
cmd.Parameters("#param").Value = id
' Use result to build up collection
Using dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection Or CommandBehavior.SingleResult Or CommandBehavior.SingleRow)
If (dr.Read()) Then
' dr then has indexed columns for each column returned for the row
End If
End Using
End Using
End Using
Like #Roland Shaw, I'd go down the datareader route but an other way.
would be to loop through
dsCustomers.Tables("Customer_Information").Rows
Don't forget to check to see if there are any rows in there.
Google VB.Net and DataRow for more info.

Why is my SqlCeResultSet only returning one row?

I am working on a Mobile 6 Classic phone application for the first time and am having problems with the SqlCeResultSet. I am trying to fill a datagrid with this:
Private Sub LookUpRoutes()
Dim dir As String = Path.GetDirectoryName(Reflection.Assembly _
.GetExecutingAssembly().GetName().CodeBase)
Dim Sql As String = "SELECT RouteID, Name, Description FROM Routes " & _
"Where IsDeleted = 0"
Using con As SqlCeConnection = New SqlCeConnection( _
String.Format("Data Source = '{0}\database\RouteTracker.sdf'", dir))
con.Open()
Using cmd As SqlCeCommand = New SqlCeCommand(Sql, con)
cmd.CommandType = CommandType.Text
Dim resultSet As SqlCeResultSet = _
cmd.ExecuteResultSet(ResultSetOptions.Scrollable)
dgRoutes.DataSource = resultSet
End Using
End Using
End Sub
However I am only getting one filled in row back from that. The remaining rows show x's in the fields instead of the data (image below).
What am I doing wrong?
My best guess is that dgRoutes is actively using the resultSet which is actively using the open connection. Presumably, to make everything operate faster, it only queries results as they are scrolled into view (ResultSetOptions.Scrollable) - therefore the connection needs to remain open so that it can pull additional data on demand.
I am not sure why this works but I got rid of the Using con As SqlCeConnection = New SqlCeConnection and just used con.open and then resisted the urge to add a con.close to the code because doing so makes it not work again.
Can someone fill me in to why I can't close and dispose the connection without breaking the functionality? Is there another way?