SQL statement to go to next available number - vb.net-2010

I have a database called DUI_Database. Inside that is a table called DUI_Cite_Numbers. In there are two columns- dui_cite_no and status. I have some code that takes a range of numbers from two text boxes and puts them in the table. Also, the status column is either FREE or ALLOCATED. ALLOCATED numbers are used and cannot be reused. FREE are just that- available numbers.
If you looked at the table, it would look like this, assuming I entered a range from D100100 to D100105
DB Name: DUI_Database
Table Name: DUI_Cite_Numbers
dui_cite_no status
D100100 FREE
D100101 FREE
D100102 FREE
D100103 FREE
D100104 FREE
D100105 FREE
Then once these numbers get used, it would look like this-
dui_cite_no status
D100100 ALLOCATED
D100101 ALLOCATED
D100102 ALLOCATED
D100103 FREE
D100104 FREE
D100105 FREE
I need help with the SELECT statement. When a form opens, I need that next FREE dui_cite_no to be used in a textbox on that form. I'm not sure how to accomplish that.
I thought this would work-
"SELECT TOP(1) dui_cite_no FROM DUI_Cite_Numbers WHERE status = 'FREE'"
It's not working- does that look right?
Because once it's used, it marks it as ALLOCATED in the column-
"UPDATE DUI_Cite_Numbers SET status = 'ALLOCATED' WHERE dui_cite_no = #nextcit"
I'm getting confused, probably because I've been starting at this for too long.
Here's the entire code chunk:
Public Function Get_Next_DUI_Cit_Number() As String
''Get the next available citation number from the database. If there is no free
''citation number then return a null string
Dim nextcit As String = String.Empty
Using DataConnection As New System.Data.SqlServerCe.SqlCeConnection("Data Source=C:\Program Files\DailyLog DUI\DUI_Database.sdf")
DataConnection.Open()
Dim SelectCommand As New System.Data.SqlServerCe.SqlCeCommand("SELECT TOP(1) dui_cite_no FROM DUI_Cite_Numbers WHERE status = 'FREE'", DataConnection)
Dim DataReader As System.Data.SqlServerCe.SqlCeDataReader = SelectCommand.ExecuteReader()
If DataReader.Read() Then
nextcit = DataReader("dui_cite_no").ToString
Using DataConnection2 As New System.Data.SqlServerCe.SqlCeConnection("Data Source=C:\Program Files\DailyLog DUI\DUI_Database.sdf")
DataConnection2.Open()
Dim UpdateCommand As New System.Data.SqlServerCe.SqlCeCommand("UPDATE DUI_Cite_Numbers SET status = 'ALLOCATED' WHERE dui_cite_no = #nextcit", DataConnection2)
UpdateCommand.Parameters.AddWithValue("#nextcit", nextcit)
UpdateCommand.ExecuteNonQuery()
UpdateCommand.Dispose()
DataConnection2.Close()
End Using
End If
SelectCommand.Dispose()
DataConnection.Close()
End Using
End Function
Then when the appropriate form opens, this is the code:
Public Sub frmDUI_Citation_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.txt_dui_cite_no.Text = module1.Get_Next_DUI_Cit_Number() 'get the next available citation number and put it in the textbox
End Sub

If you want to make sure they're issued in sequence, you need to add an ORDER BY:
SELECT TOP(1)
dui_cite_no
FROM
DUI_Cite_Numbers
WHERE
status = 'FREE'
ORDER BY
dui_cite_Number

Related

Search ms-access database via a lookup & relationship field

I'm working on a project where a form will pull information from an Access database. We have techs that are assigned to various stores, and instead of listing all of the stores and assigning a tech, I was looking to have a list of techs and assigning stores. Right now, the database has 4 fields.
Gate Tech - Text Field
Expiration Date - Date Field
Doors - Yes/No checkbox
Stores - Lookup & Relationship field that can have multiple selections
My form has a text box, search button, and a rich text box. If someone puts in a store number, it searches the Lookup & Relationship field and if that store is checked then it will put the tech in the rich text box.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim text1 As String = TextBox1.Text
myConnection.Open()
Dim lstscmd As OleDbCommand = New OleDbCommand("SELECT * FROM Table1 WHERE Stores = #Stores", myConnection)
lstscmd.Parameters.AddWithValue("#Stores", CInt(text1))
dr = lstscmd.ExecuteReader
While dr.Read
RichTextBox1.AppendText(dr("Gate Tech").ToString + Environment.NewLine)
End While
myConnection.Close()
End Sub
At While dr.Read I get
Row handles must all be released before new ones can be obtained.
I would like it search the Stores field for any selected stores, and return the Gate Tech value to the rich text box.
Any help with this would be greatly appreciated.
I found where I was going wrong and the best way to solve it.
Instead of pulling the data from the table field, I created a query in access and pointed my search to that.
Dim lstscmd As OleDbCommand = New OleDbCommand("SELECT * FROM Table1 WHERE Stores = #Stores", myConnection)
lstscmd.Parameters.AddWithValue("#Stores", CInt(text1))
Replace Table1 (or your table name) with Query1 (or your query name) and it should start pulling values.

Check if ArrayList contains an object with a property that equals a specific value

So I have an application in VB.net that is pulling data from a table and inserting it into an arraylist to be used later. What I want to do is before adding the object to the arraylist, I want to check that arraylist to see if the object exists, but I want to be able to check based off a particular property of that object.
Here is an example of what I am talking about:
Lets say Im pulling info from a table with the following columns:
InvoiceNo|DateCharged|Quantity|TotalCharge
I have a SQL statement that pulls info from a table and then I use a data reader to go through the info. My Code looks somewhat like this:
Dim dbobjM As New clsDbobjManual()
If dbobjM.Exec_SQL_DR("SELECT InvoiceNo, DateCharged, Quantity, TotalCharges From Invoices") = 0 Then
If dbobjM.DataReader.HasRows Then
Dim invoicelist As New ArrayList(5000)
Dim invoiceno As String = String.Empty
Do While dbobjM.DataReader.Read()
invoicelist.Add(New Invoice(dbobjM.DataReader.GetInt32(0), dbobjM.DataReader.Value(1), dbobjM.DataReader.GetInt32(2), dbobjM.DataReader.GetFloat(3)))
Loop
End If
End if
(Exec_SQL_DR is a function in the clsDbobjManual class that check to make sure the SQL is in the proper syntax first and checks that records are returned otherwise it returns an error)
Basically what I want to do is before I add a new object to the arraylist I want to check if an object already exists in the list where the InvoiceNo is a particular value, or the value pulled from the table each time to make sure there is no duplicates. I want one object in the list for each InvoiceNo.
Im looking for something like:
If Not invoicelist.Contains(Object where InvoiceNo = dbobjM.DataReader.GetInt32(0)) Then
invoicelist.Add
End If
But I cant seem to find what I need, any help is greatly appreciated
There is no need to use the outdated ArrayList: a List will serve you better. Please see ArrayList vs List<> in C# if you need reasons - the advantages for a list apply to VB.NET too.
Without seeing your clsDbobjManual or Invoice classes, I ended up writing the minimal code to do what you're after, which is basically the check for invoices.Any(Function(i) i.InvoiceNo = inv.InvoiceNo), which you can do if you have the data in a List(Of Invoice).
Please note that I assumed that the appropriate data types have been used in the database - you should use the Decimal type for money as otherwise you can end up with significant rounding errors, and a date should be stored as DateTime, not as a string.
Imports System.Data.SqlClient
Module Module1
Class Invoice
Property InvoiceNo As Integer
Property DateCharged As DateTime
Property Quantity As Integer
Property TotalCharges As Decimal
Sub New()
' empty constructor
End Sub
Sub New(invoiceNo As Integer, dateCharged As DateTime, quantity As Integer, totalCharges As Decimal)
Me.InvoiceNo = invoiceNo
Me.DateCharged = dateCharged
Me.Quantity = quantity
Me.TotalCharges = totalCharges
End Sub
End Class
Function LoadData() As List(Of Invoice)
Dim invoices As New List(Of Invoice)
Dim connStr As String = "your connection string"
Dim sql = "SELECT InvoiceNo, DateCharged, Quantity, TotalCharges From Invoices"
Using sqlConn As New SqlConnection(connStr)
Using sqlCmd As New SqlCommand(sql, sqlConn)
Dim reader As SqlDataReader = sqlCmd.ExecuteReader()
While reader.Read()
Dim inv As New Invoice(reader.GetInt32(0), reader.GetDateTime(1), reader.GetInt32(2), reader.GetDecimal(3))
If Not (invoices.Any(Function(i) i.InvoiceNo = inv.InvoiceNo)) Then
invoices.Add(inv)
Else
' there is a duplicate invoice number
End If
End While
End Using
End Using
Return invoices
End Function
Sub Main()
Dim uniqueInvoices As List(Of Invoice) = LoadData()
' uniqueInvoices now contains the data
End Sub
End Module
If you had a lot of invoice entries to go through, you would likely be better off writing an SQL query to do that.
If you actually just want to find duplicate invoice numbers, you could use the SQL
SELECT [InvoiceNo]
FROM testTable
GROUP BY [InvoiceNo]
HAVING COUNT([InvoiceNo]) > 1
Finally, please ensure that you are using Option Strict On so that you don't make accidental data type errors - they can drastically slow down your program and lead to erroneous results.
You can use linq to select the objects that matches your condition.
Dim result = (From invoiceitem As Invoice
In invoicelist
Where invoiceitem.InvoiceNo = dbobjM.DataReader.GetInt32(0)
Select invoiceitem).ToList()
If Not result.Count > 0 Then
invoicelist.Add(New Invoice(dbobjM.DataReader.GetInt32(0), dbobjM.DataReader.Value(1), dbobjM.DataReader.GetInt32(2), dbobjM.DataReader.GetFloat(3)))
End If

Updating a record in MS Access is not working with SQL Syntax

Could you please help me with this.
I have these codes..
Private Sub dgvInTraining_CellClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvInTraining.CellClick
If e.ColumnIndex = 0 Then
Dim transID As Integer = Me.dgvInTraining.Rows(e.RowIndex).Cells(1).Value
UPdateInTraining(transID, Now)
Else
Exit Sub
End If
End If
End Sub
Public Sub UPdateInTraining(transID, timeOut)
Try
cnn.Open()
query = "UPDATE InTraining SET TimeOut = #timeOut WHERE TransID = #transID"
cmd = New OleDbCommand(query, cnn)
cmd.Parameters.AddWithValue("#transID", transID)
cmd.Parameters.AddWithValue("#timeOut", timeOut)
cmd.ExecuteNonQuery()
Catch ex As Exception
GetErrorMessage(ex)
Finally
CloseConnection()
End Try
End Sub
Can you please tell me what I'm doing wrong. I am able to save just fine but when I try to update the record I created, it doesn't change the values in the database. My database definition follows:
TransID AutoNumber
ID Text
TimeIn Date/Time
TimeOut Date/Time
WithWater Yes/No
TransDate Date/TIme
OleDB simply uses parameters as placeholders (the names do not matter/are ignored), so you have to take care to add them in the same exact order as they appear in the SQL. Your SQL uses the order #timeOut then #transID:
"UPDATE InTraining SET TimeOut = #timeOut WHERE TransID = #transID"
But you are adding them in the opposite order:
cmd.Parameters.AddWithValue("#transID", transID)
cmd.Parameters.AddWithValue("#timeOut", timeOut)
It will be looking for a TransID of whatever the timeout value is. Swap those lines and it should work barring any other issues.
Note that MSDN suggests using "?" as a placeholder1. Doing so will force you to look back at the SQL to see which to add next. But using ? will not fix adding them in the wrong order.
Especially when there are several parameters, I prefer to use "#p1, #p2..." style parameters. The numeral helps index the column names in the SQL and you can visually see that you added them in the right order:
cmd.Parameters.AddWithValue("#p1", strBar)
cmd.Parameters.AddWithValue("#p2", nFoo)
1. In fact they say ? must be used. This is not true, it just does not map values to names but relies on the order added.

Checking for date overlap across multiple date range objects

I have several records in a database that have Start and End Dates
09/15/2011 - 09/30/2011
10/15/2011 - 10/22/2011
11/01/2011 - 11/15/2011
When user stores a record, I need to make sure dates don't overlap.
My simple code checks date ranges within a specific record (e.g. user enters 9/16/2011 or 10/21/2011, I throw an exception.)
But, on the slim chance a user gets creative (e.g. 10/14/2011 - 10/23/2011 or even 10/14/2011 to 11/16/2011), now they have circumvented my check.
BTW, the user could enter 10/14/2011 to 10/23/2011 if they were editing the record that contained values 10/15/2011 - 10/22/2011.
So, I'm trying to solve this riddle with a linq query. However, what I have isn't working exactly right.
UPDATE Nevermind about code not working. While trying to provide an example to expand on Miika's repsonse, I found my answer. So, giving credit to Miika for pointing me in the right direction and posting my working code below:
Here's my code:
Private Sub CheckForOverlap(myMonth As Messages.MyMonth)
Dim am As New MyMonth()
Dim amCollection As Messages.MyMonthCollection
Dim overlappingMyMonthDate As Boolean = False
Dim sErrorMsg As String = ""
'...non-applicable code omitted
Dim query = From s In amCollection _
Let s1 As MyMonth = CType(s, MyMonth) _
Where s1.AttendanceMonthID <> attendanceMonth.AttendanceMonthID And _
(CDate(attendanceMonth.StartDate) < CDate(s1.StartDate) And CDate(attendanceMonth.EndDate) > CDate(s1.EndDate)) _
Select s1
If query.Count > 0 Then
sErrorMsg = "Dates entered surround another entry"
End If
If overlappingMyMonthDate Then
Throw New Exception(sErrorMsg)
End If
End Sub
End Class
It all came down a LINQ query.
Do you need to do it in code or would SQL be an option? If the data is in a database, you could use the following query to check for overlaps.
SELECT COUNT(*)
FROM Table1
WHERE Table1.StartDate < 'endCheckDate'
AND Table1.EndDate > 'startCheckDate'
This will return a count of the number of overlaps found. 'endCheckDate' and 'startCheckDate' are your new query values (in date format). If your data is in a object collection in memory, then you could use LINQ. If you need help with a LINQ statement, let me know.

DataTable Select(String) Function Help VB .NET

I made a datatable with 2 columns a transactionTime column and a numberOfTransactions column. I made the table with the pre-defined transaction times and want to add the number of transactions from an XML file. I have gotten through the XML file and want to add the data to the correct row. Here is the function:
Function AddRow(ByVal timeOfTransaction As String, ByVal numberOfTransactions As String, ByRef dataTableOfTransactions As DataTable) As String
Dim row() As DataRow = dataTableOfTransactions.Select("transactionTime = timeOfTransaction")
If row(0) IsNot Nothing Then
row(0)("numberOfTransactions") = numberOfTransactions
End If
Return Nothing
End Function
When I run this it overwrites the first element in the table's numberOfTransactions coloumn. I know it has to do with the "transactionTime = timeOfTransaction" part but I can't seem to get it to read timeOfTransaction as a reference to a string instead of a literal. Any help would be much appreciated. Thanks!
You need to write something like this :
Dim row() As DataRow = dataTableOfTransactions.Select("transactionTime=#" & timeOfTransaction & "#")
But be careful with your date/month or month/date format, it depends of your regional settings.
row(0)("numberOfTransactions") = numberOfTransactions
Right there you are telling the program to overwrite that value with number of transactions.
If you want that value you need to set it to something, not set something to it.
Also, if you want your select to work properly try doing it like this
dataTableOfTransactions.Select("transactionTime = " + timeOfTransaction)