Asp.net SQL How to stop the user reserving a 'place' where there are no available seats - sql

I currently have it so that a user can reserve a seat, and the number in the database reduces by one via an SQL query. However, I can't figure out how to stop the user from reserving a seat when the number is at 0.
UPDATE Route
SET NumOfSeats = NumOfSeats - 1
WHERE ([Origin] = #Origin) and destination = #destination and DepartTime=#time
When the number of seats is at '0', the user is still able to reserve a place therefore bringing number of seats to '-1'.
Any help would be appreciated!

You could add the condition that NumOfSeats must be > 0:
Dim sql = "UPDATE Route " & vbCrLf & _
"NumOfSeats = NumOfSeats - 1 " & vbCrLf & _
"WHERE ([Origin] = #Origin) and destination = #destination and DepartTime=#time " & vbCrLf & _
"AND NumOfSeats > 0"
Using con = New SqlConnection("Connection...")
Using command As New SqlCommand(sql, con)
command.Parameters.Add("#Origin", SqlDbType.Int).Value = Origin
command.Parameters.Add("#destination", SqlDbType.Int).Value = destination
command.Parameters.Add("#destination", SqlDbType.DateTime).Value = time
con.Open()
Dim numUpdated As Int32 = command.ExecuteNonQuery()
If numUpdated = 0 Then
' tell user that no seat is available '
End If
End Using
End Using

Related

MySqlException: Column count doesn't match value count at row 1

I am trying to save multiple data to my database with this code:
repNo = MainForm.StaffMixname.Text.Substring(0, 3) & DateTime.Now.ToString("yyyyMMddhhmmss")
MetroGrid5.DataSource = Nothing
Dim ds As DataSet = New DataSet
Dim Query As String = "SELECT ci.seq_id, CONCAT(ci.lastname, ci.firstname) AS fullname, ci.amountApplied, ci.province, co.kind, co.specifications, co.regOwner, co.location FROM clientinformation ci LEFT JOIN collateraloffered co ON ci.seq_id=co.seq_id WHERE co.kind IS NOT NULL AND ci.province = '" & MetroComboBox8.Text & "' AND ci.seq_id BETWEEN '" & convertedstrFrom.ToString("yyMMdd") & "%' AND '" & convertedstrTo.ToString("yyMMdd") & "%'"
Dim fetch As New MySqlDataAdapter(Query, connect)
fetch.Fill(ds, "collateral")
MetroGrid5.DataSource = ds.Tables("collateral")
If MetroGrid5.Rows.Count > 0 Then
Dim cm As New MySqlCommand
With cm
.Connection = connect
For i As Integer = 0 To MetroGrid5.RowCount - 1
.CommandText = _
"INSERT INTO collateralrpt Values('" & repNo & _
"', '" & MetroGrid5.Rows(i).Cells("seq_id").Value & _
"', '" & MetroGrid5.Rows(i).Cells("fullname").Value & _
"', '" & MetroGrid5.Rows(i).Cells("amountApplied").Value & _
"', '" & MetroGrid5.Rows(i).Cells("kind").Value & _
"', '" & MetroGrid5.Rows(i).Cells("specifications").Value & _
"', '" & MetroGrid5.Rows(i).Cells("regOwner").Value & _
"', '" & MetroGrid5.Rows(i).Cells("location").Value & _
"', '" & MetroGrid5.Rows(i).Cells("province").Value & "')"
.ExecuteNonQuery()
Next
End With
cm.Dispose()
cm = Nothing
With connect
.Close()
.Dispose()
End With
Else
MsgBox("No Data!")
End If
but unfortunately It shows MySqlException Column count doesn't match value count at row 1.
Is there any mistake with the code above? thanks in advance.
If you want to retrieve data from one table(s) and insert into another, just use a single data adapter. You can even do so if the tables are in a different database - you just need a different connection for the SelectCommand and InsertCommand. Only a single connection is required for a single database though. E.g.
Dim selectSql = "SELECT Column1A, Column1B FROM Table1"
Dim insertSql = "INSERT INTO Table2
(
Column2A,
Column2B
)
VALUES
(
#Column2A,
#Column2B
)"
Using connection As New MySqlConnection("connection string here"),
insertCommand As New MySqlCommand(insertSql, connection),
adapter As New MySqlDataAdapter(selectSql, connection) With {.InsertCommand = insertCommand, .AcceptChangesDuringFill = False}
With insertCommand.Parameters
.Add("#Column2A", MySqlDbType.Int, 0, "Column1A")
.Add("#Column2B", MySqlDbType.VarChar, 50, "Column1B")
End With
Dim table As New DataTable
connection.Open()
adapter.Fill(table)
adapter.Update(table)
End Using
There are a few things to note here.
I wrote the SQL code using a single, multiline literal. That is far
more readable that concatenating every line.
I used parameters. That prevents numerous issues that have been
written about ad nauseum so I won't go into it here.
There's no grid control involved here. You can add one and bind the DataTable after calling Fill but that is only so you can see the data. It has nothing to do with the actual code of retrieving and saving.
The connection is opened explicitly. You can normally let a Fill or Update call open and close the connection implicitly but, in this case, we want to perform both operations and closing and reopening the connection in between is an unnecessary overhead.
The disposable objects are created with a Using statement, which means they will be implicitly disposed at the end of the block. That inclides closing the connection.
The AcceptChangesDuringFill property of the data adapter is set to True so that all RowStates are left as Added so that all DataRows are ready to be inserted.

Showing the messagebox only once in a loop vb.net

I have this loop that pops out a message box every time the condition is true.
For i = 0 To DataGridView1.Rows.Count - 1
Dim c As Boolean
c = DataGridView1.Rows(i).Cells(0).Value
If c = True Then
cmd3.Connection = con
con.Open()
cmd3.CommandText = "insert into student select * from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "' delete from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "'"
dr3 = cmd3.ExecuteReader()
MessageBox.Show("Account approved.")
con.Close()
Else
End If
Next
The messagebox shows as many times as the checked row. And I want to show it just once. I relocate my messagebox everywhere but it does not work. I searched but did not come up for an answer.
I tried moving it outside the loop but the problem is, the message box still shows even the condition is false.
Thanks!
One approach would be to create a counter for successful approvals and another counter for unsuccessful approvals and display these after completing the loop. The counters are incremented in the loop depending on the result of the boolean c in each iteration.
Dim iSuccessCount As Integer
Dim iFailedCount As Integer
For i = 0 To DataGridView1.Rows.Count - 1
Dim c As Boolean
c = DataGridView1.Rows(i).Cells(0).Value
If c = True Then
iSuccessCount +=1
cmd3.Connection = con
con.Open()
cmd3.CommandText = "insert into student select * from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "' delete from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "'"
dr3 = cmd3.ExecuteReader()
con.Close()
Else
iFailedCount += 1
End If
Next
Dim sb As New StringBuilder
sb.Append(iSuccessCount.ToString)
sb.Append(If(iSuccessCount = 1, " account was ", " accounts were "))
sb.Append("approved.")
sb.Append(Environment.NewLine)
sb.Append(iFailedCount.ToString)
sb.Append(If(iFailedCount = 1, " account was ", " accounts were "))
sb.Append("not approved.")
MessageBox.Show(sb.ToString)

How to know the available time and date in Reservation/CheckIn Program

I am using Visual Basic.Net and I have a problem in knowing the available Date, Time, and Room for the reservation/checkin of Hotel/Resort Reservation Program. Here in this code provided below, when I tried to reserve the specific room in a specific date and time, then restart the program, when I tried to save again with the unavailable room/date/time, the program's condition has wrongly allowed to save it again with the conflict schedule. I am using visual basic. Thank you :)
Dim varConflictSched As Boolean = False
Dim dsCheckIn As New DataSet
Dim daCheckIn As OdbcDataAdapter = New OdbcDataAdapter("SELECT * FROM tblCheckIn ORDER BY ID", MyConn)
daCheckIn.Fill(dsCheckIn, "tblCheckIn")
Dim DateTimeRangeNewIn(Val(Me.txtstaying.Text)) As DateTime
Dim DateCheckInNew As DateTime = Me.dtpCheckIn.Value
For a As Integer = 0 To dsCheckIn.Tables("tblCheckIn").Rows.Count - 1
Dim DateTimeRangeOldIn(dsCheckIn.Tables("tblCheckIn").Rows(a)("Staying")) As DateTime
REM Check if the room number is in used
If Me.cbRoomNumber.SelectedItem = dsCheckIn.Tables("tblCheckIn").Rows(a)("RoomNumber").ToString Then
REM Check if the date and time of the specified room number is in used
Dim varCheckInDate As DateTime = dsCheckIn.Tables("tblCheckIn").Rows(a)("CheckInDate")
For b As Integer = 0 To dsCheckIn.Tables("tblCheckIn").Rows(a)("Staying")
For c As Integer = 0 To Val(Me.txtstaying.Text)
DateTimeRangeOldIn(b) = varCheckInDate.AddDays(b)
DateTimeRangeNewIn(c) = DateCheckInNew.AddDays(c)
If DateTimeRangeOldIn(b).Date = DateTimeRangeNewIn(c).Date Then
If DateDiff(DateInterval.Minute, DateTimeRangeOldIn(b), DateTimeRangeNewIn(c)) <= 0 Then
varConflictSched = True
Exit For
End If
End If
Next
Next
End If
Next
If Me.txtAmount.Text = "" Or Me.txtSearch.Text = "" Or Me.txtstaying.Text = "" Or Me.txtTotal.Text = "" Or Me.cbRoomNumber.SelectedIndex = -1 Or Me.cbRoomtype.SelectedIndex = -1 Then
MessageBox.Show("Required field(s) should not be left blank" & vbCrLf & "Please try again", "NO BLANK SPACE", MessageBoxButtons.OK, MessageBoxIcon.Error)
ElseIf varConflictSched = True Then
MessageBox.Show("Can't set schedule with this date." & vbCrLf & "Please insert another date.", "CONFLICT", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
Dim DAdapter As OdbcDataAdapter = New OdbcDataAdapter("SELECT * FROM tblCheckIN ORDER BY ID ", MyConn)
Dim DSet As New DataSet
DAdapter.Fill(DSet, "tblCheckIN")
Dim NewID As Integer = DSet.Tables("tblCheckIN").Rows(DSet.Tables("tblCheckIN").Rows.Count - 1)("ID") + 1
Dim CommCheckIn As OdbcCommand = New OdbcCommand("INSERT INTO tblCheckIN (ID,CustomerID,Roomtype,RoomNumber,Amount,CheckInDate,Staying)VALUES(" & NewID & ",'" & Me.txtSearch.Text & "','" & Me.cbRoomtype.SelectedItem & "','" & Me.cbRoomNumber.SelectedItem & "','" & Me.txtAmount.Text & "','" & Me.dtpCheckIn.Value & "' , '" & Me.txtstaying.Text & "')", MyConn)
MyConn.Open()
CommCheckIn.ExecuteNonQuery()
MyConn.Close()
MessageBox.Show("Your Checking-In is succesfully saved. ", "SAVED", MessageBoxButtons.OK, MessageBoxIcon.Information)
Me.ClearAll()
End If
You don’t need looping code to find a collision.
A collision occurs when:
RequestionStartDate <= EndDate
And
RequestEndDate >= StartDate
Of course you have to add roomnumber to above, but it rather simple.
So on book button, your code will do this:
Dim strSQL As String
Dim rstData As New DataSet
Dim daRead As SqlDataAdapter
strSQL = "select * from tblCheckIn where RoomNumber = #RoomNum " & _
" AND ( (#CheckIn <= CheckOutDate) AND (#CheckOut >= CheckInDate) )"
Dim MySql As SqlCommand = New SqlCommand(strSQL, GetCon)
MySql.Parameters.Add("#RoomNum", SqlDbType.Int).Value = Me.RoomNumber.Value
MySql.Parameters.Add("#CheckIn", SqlDbType.DateTime).Value = Me.dtpCheckIn.Value
MySql.Parameters.Add("#CheckOut", SqlDbType.DateTime).Value = Me.dtpCheckOut.Value
daRead.SelectCommand = MySql
daRead.Fill(rstData)
If rstData.Tables(0).Rows.Count > 0 Then
MsgBox("you have a booking collsion")
End If
The above works since you never allow a collsion, and the above will return any record that you "over lap". this includes the cases like this:
RequestStart RequestEnd
| |
| exsiting Start/end |
or
RequestStart RequestEnd
| |
| exist Start Exist end |
or
RequestStart RequestEnd
| |
| exist Start Exist end |
in fact any combination of ANY overlap will be found by the above simple query.

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;

too slow in show report in vb.net 2010 using crytal report

I am using this code to show the report
Dim rpt As New CrystalReport1()
Dim sql As String
Dim where As String
If con Is Nothing OrElse con.State = ConnectionState.Closed Then
'MsgBox("closed")
OpenCon()
End If
Dim m As String
m = ""
For Each n As TreeNode In GetCheck(TreeView1.Nodes)
If n.Tag = 1 Then
m = m
Else
If m = "" Then
m = (n.Tag)
Else
m = m & ", " & (n.Tag)
End If
End If
Next
sql = "SELECT [bran_id],[f01],[f02],[f03],[f04],[f05],[f06],[f07],[f08],[bran_name],[comp_id],[comp_name],'" & dtStart.Value.Date & "' AS start_date, '" & dtEnd.Value.Date & "' AS end_date FROM [v_complain]"
If m = "" Then
MsgBox("لم يتم تحديد اى مدينة من فضلك قم بالاختيار اولا")
Exit Sub
Else
where = " WHERE bran_id in (" & m & ") and f02 between CONVERT(date,'" & dtStart.Value.Date & "',103) and CONVERT(date,'" & dtEnd.Value.Date & "',103)"
sql = sql + where
If cbF06.Checked = True Then
where = " AND (f06 like N'') or (f06 is null)"
sql = sql + where
End If
If cbF07.Checked = True Then
where = " AND (f07 like N'') or (f07 is null)"
sql = sql + where
End If
Dim dscmd As New SqlDataAdapter(sql, con)
Dim ds As New DataTable
dscmd.Fill(ds)
rpt.SetDataSource(ds)
CrystalReportViewer1.ReportSource = rpt
CrystalReportViewer1.Refresh()
End If
con.Close()
but it's too slow to show the report in the first time. When I try to run it again without closing the window it work perfectly. Is there any way to make it faster?
Thanks
How slow it is? Several seconds?
I believe it happens do to a need to initialize underling reports 'engine'. I had similar issues and the best I could come up with was to display "Creating report, please wait..." message to a user so they. As an alternative, when you start your app, you can make a 'fake' call to create a dummy report in the background without displaying anything to a user so all required resources will be initialized by the time user is ready to create a real report.