Update sqlite query not working in Visual Basic 2013 - vb.net

I am trying to insert row and update row (if row already exists), as following -
Dim con As SQLiteConnection
Dim sql As String
Dim cmd As New SQLiteCommand
Dim da As SQLiteDataAdapter
Dim ds As New DataSet
Dim NumberOfRows As Integer
Public Sub UpdateUserStatistics(ByVal UserId As Integer, ByVal QId As Integer, _
ByVal KeyName As String, ByVal KeyValue As Integer)
con = New SQLiteConnection("Data Source = " + AppDomain.CurrentDomain.BaseDirectory + "/user_statistics.db;Version=3;")
con.Open()
sql = "SELECT * FROM med_user_meta where user_id=" & UserId & " And qid=" & QId
da = New SQLiteDataAdapter(sql, con)
da.Fill(ds, "UserMeta")
NumberOfRows = ds.Tables("UserMeta").Rows.Count
ds.Clear()
If (NumberOfRows = 0) Then
Dim InsertQuery As SQLiteCommand = con.CreateCommand
InsertQuery.CommandText = "INSERT INTO med_user_meta " _
& "(user_id, qid, " _
& KeyName _
& ", timestamp) VALUES(?, ?, ?, datetime('now'))"
InsertQuery.Parameters.AddWithValue("user_id", UserId)
InsertQuery.Parameters.AddWithValue("qid", QId)
InsertQuery.Parameters.AddWithValue(KeyName, KeyValue)
RowInserted = InsertQuery.ExecuteNonQuery()
ElseIf (NumberOfRows = 1) Then
Dim UpdateQuery As SQLiteCommand = con.CreateCommand
UpdateQuery.CommandText = "UPDATE med_user_meta SET " _
& KeyName _
& " = ?, timestamp = datetime('now') Where qid = ?"
'UpdateQuery.Parameters.AddWithValue("user_id", UserId)
UpdateQuery.Parameters.AddWithValue("qid", QId)
UpdateQuery.Parameters.AddWithValue(KeyName, KeyValue)
RowUpdated = UpdateQuery.ExecuteNonQuery()
End If
con.Close()
End Sub
I am using this code in a module and calling UpdateUserStatistics wherever required
My problem is that, insert query works fine, but update query does Not work.
It's been more than 2 hours, but I couldn't find, where am I making mistake?
Also, is there any way to get the final update query into message box after adding parameters, so that I can check if my final update query is correct?
Edit - 1
I forgot to mention, value of RowUpdated is returning 0, i.e. ExecuteNonQuery is Not updating the row.
I have also confirmed that row corresponding to update query Do exists, and the ElseIf (NumberOfRows = 1) Then block is running too, but it's Not updating the row.

Related

VB.NET update same table inside a DataReader loop

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)

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.

Cannot open any more tables - OleDbException was unhandled

Good Day,
My question is how to handle the exception or get rid of the error pertaining to "Cannot open any more tables". For an overview to the program I was creating, I pull out the record of subject in ms access 2007, I loop to that record to randomly assign a schedule and one by one I insert the newly record with assigned schedule in the table.
My program flow of inserting the record work only for a certain number of times, like almost 200 and at some point it stop and pop-up the oledbexception
Thanks in advance for your time on answering my question.
here is my code for more detailed overview of my program,
Private Sub Assignsched(ByVal rType As String, ByVal subjectCode As String, ByVal SecID As String, ByVal CourseCode As String)
If shrdcon.con.State = ConnectionState.Closed Then
shrdcon.con.Open()
End If
Dim RoomNum As Integer
dtARoom.Clear()
Dim stoploop As Boolean
Dim count As Integer = 0
Dim rm1 As String
RoomAssign = ""
rm1 = "SELECT * FROM tblRoom WHERE RoomType = '" & rType & "'"
Dim dat As New OleDbDataAdapter(rm1, shrdcon.con)
dat.Fill(ds, "ARoom")
stoploop = False
count = 0
Do Until stoploop = "True"
RoomNum = rndm.Next(0, ds.Tables("ARoom").Rows.Count)
RoomAssign = ds.Tables("ARoom").Rows(RoomNum).Item(1)
ScheduleGeneration()
If checkExisting(sTime, eTime, RoomAssign, daypick) = False Then
RoomA = RoomAssign
GenerateOfferingID()
Dim cmd1 As New OleDbCommand()
cmd1.CommandText = "INSERT INTO [tblSubjectOffer]([SubjectOID],[SubjectCode],[SectionID],[Day],[sTime],[eTime],[RoomName],[CourseCode]) VALUES('" & _
myId & "','" & subjectCode & "','" & SecID & "','" & daypick & "'," & sTime & "," & eTime & ",'" & RoomA & "','" & CourseCode & "')"
cmd1.Connection = shrdcon.con
cmd1.ExecuteNonQuery()
cmd1.Dispose()
Dim pipz As New OleDbCommand("Update tblGenerator Set NextNo='" & myId & "' where TableName ='" & "tblSubjectOffer" & "'", shrdcon.con)
pipz.ExecuteNonQuery()
pipz.Dispose()
stoploop = True
Else
stoploop = False
End If
If stoploop = False Then
If count = 30 Then
stoploop = True
Else
count = count + 1
End If
End If
Loop
End Sub
This is typical error happens with Microsoft Jet engine when You have exceeded the maximum number of open TableIDs allowed by the Microsoft Jet database engine, which is 2048 with Jet3.5 engine and 1024 with older engines.
Even though you are closing the Command objects after each use, you are still using the same connection for the whole process, which actually holds the TableID's and is at some point of time exceeding the number of allowed open TableID's.
A probable solution would be to update the Jet Engine with the latest, which is available here
It might solve your problem, but if you are already using the latest engine, you have to look into other options to reduce the number of DB operations.
Try using the UpdateBatch method for applying the updates as a batch.
Hope this helps
Private Sub Command1_Click()
Dim myConnection As ADODB.Connection
Dim rsData As ADODB.Recordset
Set myConnection = New ADODB.Connection
myConnection.ConnectionString = "xxxxxxxxxxxxxxxxxxxx"
myConnection.Open
Set rsData = New ADODB.Recordset
rsData.CursorLocation = adUseClient
rsData.Open "select * from mytable", myConnection, adOpenStatic, adLockBatchOptimistic
For i = 1 To 10000
rsData.AddNew
rsData.Fields(0).Value = 1
rsData.Fields(1).Value = 2
Next i
rsData.UpdateBatch
rsData.Close
myConnection.Close
Set rsData = Nothing
End Sub
Good Evening,
Recently I encounter this type of error and i was able to resolve it by adding
con.close and call conState (a procedure conState- check below) before any insert/update or select statement
In my code i have something like
For i = 0 To DataGridView1.RowCount - 1
reg = DataGridView1.Rows(i).Cells(0).Value
Label2.Text = reg
'i added this two lines
***con.Close()***
***Call conState()***
Dim cmdcheck As New OleDbCommand("Select * from [2015/2016 UG CRF] where regno ='" & reg & "'", con)
Dim drcheck As OleDbDataReader
drcheck = cmdcheck.ExecuteReader
If drcheck.Read = True Then
GoTo A
End If
coursesFirst = String.Empty
coursesSecond = String.Empty
creditFirst = 0
creditSecond = 0
Dim cmdlevel As New OleDbCommand("Select * from [2015/2016 UG registration Biodata 5 april 16] where regno ='" & reg & "'", con)
Dim drlevel As OleDbDataReader
drlevel = cmdlevel.ExecuteReader
If drlevel.Read = True Then
level = drlevel.Item("level").ToString
faculty = drlevel.Item("faculty").ToString
program = drlevel.Item("programme").ToString
End If
...............
next
The conState is a connection testing if connection is closed is should open it again like in below
Public Sub conState()
If con.State = ConnectionState.Closed Then
con.Open()
End If
End Sub
This stop the error message
I got this exception in my C# application and the cause was using OleDbDataReader instances without closing them:
OleDbDataReader reader = cmd.ExecuteReader();
bool result = reader.Read();
reader.Close(); // <= Problem went away after adding this
return result;

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()

Object reference not set to an instance of an object. For Loop

Function FindUserByCriteria(ByVal _state As String, ByVal _county As String, ByVal _status As String, ByVal _client As String, ByVal _department As String, ByVal _ordernumber As String) As DataTable
'Code to load user criteria from database
Dim ordertype As String
If _status = "Online" Then
ordertype = "Online"
ElseIf _status = "Tax Cert Call" Then
ordertype = "Call"
End If
Dim TaxConnStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ConfigurationManager.AppSettings("Database")
Dim dbConnection As OleDbConnection = New OleDbConnection(TaxConnStr)
Try
Dim queryString As String
queryString = "Select Username, Amount, Rank FROM UserCriteria "
queryString += "WHERE UserCriteria.State = '" & _state & "' AND UserCriteria.County = '" & _county & "' AND UserCriteria.Status = '" & _status & "' AND UserCriteria.Client = '" & _client & "' AND UserCriteria.Department = '" & _department & "' AND UserCriteria.OrderNumber = '" & _ordernumber & "';"
Dim dbCommand As OleDbCommand = New OleDbCommand
dbCommand.CommandText = queryString
dbCommand.Connection = dbConnection
Dim dataAdapter As OleDbDataAdapter = New OleDbDataAdapter
dataAdapter.SelectCommand = dbCommand
Dim dataSet As DataSet = New DataSet
dataAdapter.Fill(dataSet)
If dataSet.Tables(0).Rows.Count >= 1 Then
FindUserByCriteria = dataSet.Tables(0)
End If
Console.WriteLine(vbCrLf)
For i = 0 To FindUserByCriteria.Rows.Count - 1
If Not IsUserOnline(FindUserByCriteria.Rows(i).Item("UserName")) Then
FindUserByCriteria.Rows(i).Delete()
End If
Next
FindUserByCriteria.AcceptChanges()
Catch ex As Exception
Console.WriteLine(ex.Message)
myLogger.Log(ex.Message)
SendMail(ex.Message)
Finally
dbConnection.Close()
End Try
End Function
So, i get the "Object reference not set to an instance of an object." error at the
For i = 0 To FindUserByCriteria.Rows.Count - 1
line. I swear this was working for me not just 3 days ago...not sure what has changed in my code recently to make this error pop up. Any help would be nice.
you need to reverse the for loop for
For i = FindUserByCriteria.Rows.Count - 1 to 0 step -1
you need to delete backward otherwise you will reach an index already deleted
or you simply need to put the use of any FindUserByCriteria inside the if where it get set
If dataSet.Tables(0).Rows.Count >= 1 Then
FindUserByCriteria = dataSet.Tables(0)
Console.WriteLine(vbCrLf)
For i = 0 To FindUserByCriteria.Rows.Count - 1
If Not IsUserOnline(FindUserByCriteria.Rows(i).Item("UserName")) Then
FindUserByCriteria.Rows(i).Delete()
End If
Next
FindUserByCriteria.AcceptChanges()
End If