0

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

Kristen
  • 443
  • 1
  • 12
  • 25
  • It seems like you better use `List` than `ArrayList` since your object is of the same type -> the data row – Ian Jan 15 '16 at 16:33

2 Answers2

2

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.

Community
  • 1
  • 1
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
1

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 
Abner
  • 416
  • 5
  • 18