VB.NET update same table inside a DataReader loop - sql

I'm reading from a SQL database and depending on the fields I check I need to update a different field in that same table. I'm looping through the dataset and trying to send an UPDATE back while looping. It worked on my TEST table but isn't working for my production table. When I execute the "ExecuteNonQuery" command, I get a timeout expired error. If I actually close the first connection and then call the ExecuteNonQuery it runs instantly.
Here's the code...
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim sqlConn As New SqlConnection
Dim sqlComm As New SqlCommand
Dim sqlDR As SqlDataReader
sqlConn.ConnectionString = "Data Source=10.2.0.87;Initial Catalog=Inbound_Orders_DB;User ID=xxxxx;Password=xxxxxx;"
sqlConn.Open()
sqlComm.CommandText = "SELECT * FROM RH_Orders where Order_DateTime is NULL ORDER by Order_Date DESC"
sqlComm.Connection = sqlConn
sqlDR = sqlComm.ExecuteReader
If sqlDR.HasRows Then
While sqlDR.Read
If Trim(sqlDR("Order_Date")) <> "" Then
Dim order_Date As String = Trim(sqlDR("Order_Date"))
Dim order_DateTime As String = ""
If Len(order_Date) = 14 Then
order_DateTime = order_Date.Substring(0, 4) & "-" & order_Date.Substring(4, 2) & "-" & order_Date.Substring(6, 2) & " "
order_DateTime = order_DateTime & order_Date.Substring(8, 2) & ":" & order_Date.Substring(10, 2) & ":" & order_Date.Substring(12, 2)
Dim myId As String = sqlDR("ID")
Dim sqlConn2 As New SqlConnection
Dim sqlComm2 As New SqlCommand
sqlConn2.ConnectionString = "Data Source=10.2.0.87;Initial Catalog=Inbound_Orders_DB;User ID=xxxx;Password=xxxx;"
sqlConn2.Open()
sqlComm2.CommandText = "UPDATE [RH_Orders] SET order_DateTime = '" & order_DateTime & "' WHERE ID=" & myId
sqlComm2.Connection = sqlConn2
sqlComm2.ExecuteNonQuery()
sqlConn2.Close()
End If
End If
End While
End If
End Sub
End Class

Use parametrized queries and don't concatenate strings, then use a SqlParameter with SqlDbType.Datetime and assign a real DateTime instead of a formatted string.
But maybe it would be more efficient here to fill a DataTable with SqlDataAdapter.Fill(table), loop the table's Rows, change each DataRow and use SqlDataAdapter.Update(table) to send all changes in one batch after the loop. No need for the SqlDataReader loop.
For example (untested):
Using con = New SqlConnection("Data Source=10.2.0.87;Initial Catalog=Inbound_Orders_DB;User ID=xxxxx;Password=xxxxxx;")
Using da = New SqlDataAdapter("SELECT * FROM RH_Orders where Order_DateTime is NULL ORDER by Order_Date DESC", con)
da.UpdateCommand = New SqlCommand("UPDATE RH_Orders SET order_DateTime = #order_DateTime WHERE ID = #Id", con)
da.UpdateCommand.Parameters.Add("#order_DateTime", SqlDbType.DateTime).SourceColumn = "order_DateTime"
Dim table = New DataTable()
da.Fill(table)
For Each row As DataRow In table.Rows
Dim orderDate = row.Field(Of String)("Order_Date")
Dim orderDateTime As DateTime
If DateTime.TryParse(orderDate.Substring(0, 4) & "-" & orderDate.Substring(4, 2) & "-" & orderDate.Substring(6, 2), orderDateTime) Then
row.SetField("order_DateTime", orderDateTime)
End If
Next
da.Update(table)
End Using
End Using
Side-note: Instead of building a new string "2017-01-31" from "20170131" you could also use DateTime.TryParseExact:
DateTime.TryParseExact("20170131", "yyyyMMdd", nothing, DateTimeStyles.None, orderDateTime)

Related

I want to query between two dates in sqlite with two textbox(textbox4.text and textbox5.text = variable) in form

Dim query As String = "select * from mytable where strftime('%Y-%m-%d',tarih) between 'TextBox4.text' and 'TextBox5.text' "
Can not assign query variable ?
Datagridview result = empty
info :Datagridview date format = 2018-01-01 17:42:24
Dim btarihyil As String
btarihyil = DateTimePicker2.Value.ToString.Substring(6, 4)
Dim btarihay As String
btarihay = DateTimePicker2.Value.ToString.Substring(3, 2)
Dim btarihgun As String
btarihgun = DateTimePicker2.Value.ToString.Substring(0, 2)
TextBox4.Text = btarihyil & "-" & btarihay & "-" & btarihgun
Dim bttarihyil As String
bttarihyil = DateTimePicker3.Value.ToString.Substring(6, 4)
Dim bttarihay As String
bttarihay = DateTimePicker3.Value.ToString.Substring(3, 2)
Dim bttarihgun As String
bttarihgun = DateTimePicker3.Value.ToString.Substring(0, 2)
TextBox4.Text = btarihyil & "-" & btarihay & "-" & btarihgun
TextBox5.Text = bttarihyil & "-" & bttarihay & "-" & bttarihgun
Dim Yol As String = "Data Source=database1.s3db;version=3;new=False"
Using MyConn As New SQLiteConnection(Yol)
If (MyConn.State = ConnectionState.Closed) Then
MyConn.Open()
End If
Dim Sorgu As String = "select * from mytable where strftime('%Y-%m-%d',tarih) between 'TextBox4.text' and 'TextBox5.text' "
Using MyCmd As New SQLiteCommand(Sorgu, MyConn)
Dim Da As New SQLiteDataAdapter(MyCmd)
Dim Ds As New DataSet
Dim Dt As New DataTable
Ds.Reset()
Da.Fill(Ds)
Dt = Ds.Tables(0)
Dim Bs As New BindingSource With {.DataSource = Dt}
DataGridView1.DataSource = Bs
Bs.MoveLast()
MyConn.Close()
MyCmd.Dispose()
MyConn.Dispose()
End Using
End Using
End Sub
You are using "TextBox4.Text" and "TextBox5.Text" literally in the query. That will not pass the values of textboxes to the query. So it will result in error.
Also you need to use parameterized query to avoid syntax errors.
Also I am not sure why you are using strftime function. That function is used just for formatting.
Following the code I re-written using parameterzied query approach.
Dim Yol As String = "Data Source=database1.s3db;version=3;new=False"
Using MyConn As New SQLiteConnection(Yol)
If (MyConn.State = ConnectionState.Closed) Then
MyConn.Open()
End If
Dim Sorgu As String = "select * from mytable where tarih between #startDate and #endDate "
Using MyCmd As New SQLiteCommand(Sorgu, MyConn)
Dim startDate as new SQLiteParameter("#startDate")
startDate.Value = DateTimePicker2.Value
Dim endDate as new SQLiteParameter("#endDate")
endDate.Value = DateTimePicker3.Value
MyCmd.Parameters.Add(startDate)
MyCmd.Parameters.Add(endDate)
Dim Da As New SQLiteDataAdapter(MyCmd)
Dim Ds As New DataSet
Dim Dt As New DataTable
Ds.Reset()
Da.Fill(Ds)
Dt = Ds.Tables(0)
Dim Bs As New BindingSource With {.DataSource = Dt}
DataGridView1.DataSource = Bs
Bs.MoveLast()
MyConn.Close()
MyCmd.Dispose()
MyConn.Dispose()
End Using
End Using
This should help you resolve your issue.

Access Database VB - Searching a database for most 'RECENT' record

I was wondering how I could change the code below, to allow me to search for the most recent record. I am creating a Hotel Booking System and want to use the most recent price in the database but at the moment, it is just searching using the labels which I don't want.
Dim str1 As String
Dim dbpassword As String = "123"
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source= E:\Computing\Hotel Booking System\Database\Hotel Booking System.accdb ;Jet OLEDB:Database Password =" & dbpassword & ";"
Dim MyConn As OleDbConnection
Dim dr As OleDbDataReader
Private Sub Information_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim PriceFound As String = False
MyConn = New OleDbConnection
MyConn.ConnectionString = connString
MyConn.Open()
str1 = ("SELECT * FROM [Prices] WHERE [Adult] = '" & LblPriceAdult.Text & "' AND [Child] = '" & LblPriceChild.Text & "'")
Dim cmd1 As OleDbCommand = New OleDbCommand(str1, MyConn)
dr = cmd1.ExecuteReader
While dr.Read()
PriceFound = True
DateDisplay = dr("ID").ToString
AdultPrice = dr("Adult").ToString
ChildPrice = dr("Child").ToString
SingleRoom = dr("Single").ToString
DoubleRoom = dr("Double").ToString
FamilyRoom = dr("Family").ToString
If PriceFound = True Then
LblPriceAdult.Text = AdultPrice
LblPriceChild.Text = ChildPrice
LblPriceDoubleRoom.Text = DoubleRoom
LblPriceFamilyRoom.Text = FamilyRoom
LblPriceSingleRoom.Text = SingleRoom
End If
End While
MyConn.Close()
End Sub
Based on your previous comments, you need to rewrite your SQL to trap the most recent record.
Try something like this:
SELECT MAX(ID) FROM [Prices] ORDER BY ID DESC
I tried the answer above. However for the code above, it wouldn't search for the most recent so I changed DESC to ASC

Excel to Sql adding certain rows to sql server

cmd.CommandText = (Convert.ToString("SELECT * From [") & excelSheet) & "] Order By" & columnCompany & "OFFSET 0 ROWS FETCH NEXT 100000 ROWS ONLY "
I am trying to map data form excel to an sql table but the excel table has a lot of records in it, so I run out of memory if I try to add all of the records at once. So what I am trying to do is use this line of code
cmd.CommandText = (Convert.ToString("SELECT * From [") & excelSheet) & "] Order By B OFFSET 0 ROWS FETCH NEXT 100000 ROWS ONLY "
So that 100000 row will be added. Then I intend to clear the data table and do the same only from 100001 to 200000 and so on.
But I cant get this to work correctly, it works fine when it is just SELECT TOP 100000 FROM... but then I dont know how to get the next 100000 record. I think the Order By is where the issue is as I'm not sure how to get the correct column.
Here is my code Below
Private Sub btnMap_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMap.Click
'Allows columns to be moved mapped in the correct order
Dim nbColumnsToTransfer As Integer = dgvMapped.Columns.GetColumnCount(1)
Dim indexes As List(Of Integer) = (From column As DataGridViewColumn In dgvLoadedata.Columns.Cast(Of DataGridViewColumn)() _
Take nbColumnsToTransfer _
Order By column.DisplayIndex _
Select column.Index).ToList()
Dim columnCompany As Integer = indexes(0)
Dim columnEmail As Integer = indexes(1)
Dim columnFirstName As Integer = indexes(2)
Dim columnSurname As Integer = indexes(3)
Dim columnPostCode As Integer = indexes(4)
Dim columnTelephone As Integer = indexes(5)
Dim columnEmployeeBand As Integer = indexes(6)
Dim DeleteConnection As New Data.SqlClient.SqlConnection
DeleteConnection.ConnectionString = "Data Source=DC01\SQLEXPRESS;Initial Catalog=YCM;User ID=sa;Password=S0rtmypc!"
DeleteConnection.Open()
Dim sqlDTM As String = "Delete From TempMapped"
Dim command As New SqlCommand(sqlDTM, DeleteConnection)
command.ExecuteNonQuery()
Dim sqlDTSR As String = "Delete From TempSplitReq"
command = New SqlCommand(sqlDTSR, DeleteConnection)
command.ExecuteNonQuery()
DeleteConnection.Close()
If chkContactSplitReq.Checked = True Then
Dim dt As New DataTable()
Using con As New OleDbConnection(conString)
Using cmd As New OleDbCommand()
Using oda As New OleDbDataAdapter()
cmd.CommandText = (Convert.ToString("SELECT * From [") & excelSheet) & "] Order By" & columnCompany & "OFFSET 0 ROWS FETCH NEXT 100000 ROWS ONLY ""
cmd.Connection = con
con.Open()
oda.SelectCommand = cmd
oda.Fill(dt)
con.Close()
End Using
End Using
End Using
Dim connection As String = "Data Source=DC01\SQLEXPRESS;Initial Catalog=YCM;User ID=sa;Password=S0rtmypc!"
Using cn As New SqlConnection(connection)
cn.Open()
Using copy As New SqlBulkCopy(cn)
copy.ColumnMappings.Add(columnCompany, 0)
copy.ColumnMappings.Add(columnEmail, 1)
copy.ColumnMappings.Add(columnFirstName, 2)
copy.ColumnMappings.Add(columnPostCode, 3)
copy.ColumnMappings.Add(columnTelephone, 4)
copy.DestinationTableName = "TempSplitReq"
copy.WriteToServer(dt)
End Using
End Using
Dim SplitConnection As New Data.SqlClient.SqlConnection
SplitConnection.ConnectionString = "Data Source=DC01\SQLEXPRESS;Initial Catalog=YCM;User ID=sa;Password=S0rtmypc!"
SplitConnection.Open()
Dim sqlSplit As String = "TempSplitReq_SaveToMapped"
Dim commandSplit As New SqlCommand(sqlSplit, SplitConnection)
commandSplit.ExecuteNonQuery()
SplitConnection.Close()
Else
Dim dt As New DataTable()
Using con As New OleDbConnection(conString)
Using cmd As New OleDbCommand()
Using oda As New OleDbDataAdapter()
cmd.CommandText = (Convert.ToString("SELECT * From [") & excelSheet) + "] "
cmd.Connection = con
con.Open()
oda.SelectCommand = cmd
oda.Fill(dt)
con.Close()
End Using
End Using
End Using
Dim connection As String = "Data Source=DC01\SQLEXPRESS;Initial Catalog=YCM;User ID=sa;Password=S0rtmypc!"
Using cn As New SqlConnection(connection)
cn.Open()
Using copy As New SqlBulkCopy(cn)
copy.ColumnMappings.Add(columnCompany, 0)
copy.ColumnMappings.Add(columnEmail, 1)
copy.ColumnMappings.Add(columnFirstName, 2)
copy.ColumnMappings.Add(columnSurname, 3)
copy.ColumnMappings.Add(columnPostCode, 4)
copy.ColumnMappings.Add(columnTelephone, 5)
copy.DestinationTableName = "TempMapped"
copy.WriteToServer(dt)
End Using
End Using
End If
MsgBox("Data Mapping Complete")
End Sub
A SqlBulkCopy object has a BatchSize property. I have a similar situation and set
copy.BatchSize = 1000
And mine works with a large spreadsheet import. Adjust this property in your environment for better performance.

How to create a query in Visual Studio 2013 using Visual Basic

I have the following code and through debugging the problem begins at the While loop. I am trying to retrieve information from 2 tables and insert it into the table created. The information is not being inserted into the table and I am getting blank rows.
Imports System.Data.OleDb
Public Class RouteToCruise
Private Sub RouteToCruise_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Route_Btn_Click(sender As Object, e As EventArgs) Handles Route_Btn.Click
Dim row As String
Dim connectString As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=M:\ICT-Group-Project\DeepBlueProject\DeepBlueProject\DeepBlueTables.mdb"
Dim cn As OleDbConnection = New OleDbConnection(connectString)
cn.Open()
Dim CruiseQuery As String = "SELECT CruiseID, RouteID FROM Cruise WHERE CruiseID =?"
Dim RouteQuery As String = "SELECT RouteName FROM Route WHERE RouteID =?"
Dim cmd As OleDbCommand = New OleDbCommand(CruiseQuery, cn)
Dim cmd2 As OleDbCommand = New OleDbCommand(RouteQuery, cn)
cmd.Parameters.AddWithValue("?", Route_Txt.Text)
Dim reader As OleDbDataReader
reader = cmd.ExecuteReader
'RCTable.Width = Unit.Percentage(90.0)
RCTable.ColumnCount = 2
RCTable.Rows.Add()
RCTable.Columns(0).Name = "CruiseID"
RCTable.Columns(1).Name = "Route"
While reader.Read()
Dim rID As String = reader("RouteID").ToString()
cmd2.Parameters.AddWithValue("?", rID)
Dim reader2 As OleDbDataReader = cmd2.ExecuteReader()
'MsgBox(reader.GetValue(0) & "," & reader.GetValue(1))
row = reader("CruiseID") & "," & reader2("RouteName")
RCTable.Rows.Add(row)
cmd.ExecuteNonQuery()
reader2.Close()
End While
reader.Close()
cn.Close()
End Sub
End Class
If I understand your tables structure well then you could just run a single query extracting data from the two table and joining them in a new table returned by the query
Dim sql = "SELECT c.CruiseID c.CruiseID & ',' & r.RouteName as Route " & _
"FROM Cruise c INNER JOIN Route r ON c.RouteID = c.RouteID " & _
" WHERE c.CruiseID = #cruiseID"
Dim cmd As OleDbCommand = New OleDbCommand(sql, cn)
cmd.Parameters.Add("#cruiseID", OleDbType.Int).Value = Convert.ToInt32(Route_Txt.Text)
Dim RCTable = new DataTable()
Dim reader = cmd.ExecuteReader()
reader.Load(RCTable)
At this point the RCTable is filled with the data coming from the two tables and selected using the Route_Txt textbox converted to an integer. If the CruiseID field is not a numeric field then you should create the parameter as of type OleDbType.VarWChar and remove the conversion to integer
Try simplifying your query.
Dim CruiseRouteQuery As String = "SELECT C.CruiseID, C.RoutID, R.Routename FROM Cruise C LEFT JOIN Route R ON C.RouteID = R.RoutID WHERE CruiseID =?"
Also, please let us know what errors you are getting.

Getting Primary key values (auto number ) VB

I have a database on Access and I want to insert into 2 tables
ReportReq
req_sysino
I want to get the last value of primary key (auto numbered) and insert it into req_sysino
, I am stuck with this code and I dont know how to proccess
Private Function InsertSysInvToDB(intSysInv As Integer) As Integer
Dim strSQLStatement As String = String.Empty
Dim intNoAffectedRows As Integer = 0
Dim con As New OleDb.OleDbConnection("PROVIDER = Microsoft.ace.OLEDB.12.0; Data Source = C:\Users\felmbanF\Documents\Visual Studio 2012\Projects\WebApplication3\WebApplication3\App_Data\ReportReq.accdb")
Dim cmd As OleDb.OleDbCommand
Dim reqnum As String = "Select ##REQ_NUM from ReportReq"
strSQLStatement = "INSERT INTO req_sysino (Req_num, sysinvo_ID)" +
" VALUES (" & reqnum & "','" & intSysInv & ")"
cmd = New OleDb.OleDbCommand(strSQLStatement, con)
cmd.Connection.Open()
intNoAffectedRows = cmd.ExecuteNonQuery()
cmd.Connection.Close()
Return intNoAffectedRows
End Function
this is my insert code that should generate autonumber
Dim dbProvider = "PROVIDER = Microsoft.ace.OLEDB.12.0;"
Dim dbSource = " Data Source = C:\Users\felmbanF\Documents\Visual Studio 2012\Projects\WebApplication3\WebApplication3\App_Data\ReportReq.accdb"
Dim sql = "INSERT INTO ReportReq (Emp_EmpID, Req_Date,Req_expecDate,Req_repnum, Req_name, Req_Descrip, Req_columns, Req_Filtes, Req_Prompts)" +
"VALUES (#reqNUM,#reqName,#reqDescrip,#reqcolumns,#reqfilters,#reqprompts)"
Using con = New OleDb.OleDbConnection(dbProvider & dbSource)
Using cmd = New OleDb.OleDbCommand(sql, con)
con.Open()
cmd.Parameters.AddWithValue("#EmpID", txtEmpID.Text)
cmd.Parameters.AddWithValue("#reqDate", DateTime.Today)
cmd.Parameters.AddWithValue("#reqExpecDate", DateTime.Parse(txtbxExpecDate.Text).ToShortDateString())
cmd.Parameters.AddWithValue("#reqNUM", txtRep_NUM.Text)
cmd.Parameters.AddWithValue("#reqName", txtRep_Name.Text)
cmd.Parameters.AddWithValue("#reqDescrip", txtbxRep_Desc.Text)
cmd.Parameters.AddWithValue("#reqcolumns", txtbxColReq.Text)
cmd.Parameters.AddWithValue("#reqfilters", txtbxFilReq.Text)
cmd.Parameters.AddWithValue("#reqprompts", txtbxPromReq.Text)
cmd.ExecuteNonQuery()
End Using
End Using
Immediately after you ExecuteNonQuery() your INSERT INTO ReportReq ... statement you need to run a
SELECT ##IDENTITY
query and retrieve its result, like this
cmd.ExecuteNonQuery() ' your existing statement to run INSERT INTO ReportReq
cmd.CommandText = "SELECT ##IDENTITY"
Dim newAutoNumberValue As Integer = cmd.ExecuteScalar()