views:

33

answers:

2
  • listA is list of integer

  • dtListB is DataTable

I'm checking that if StudentId of ListA doesn't exist in dtListB, then add it to the dtListB.

Dim stidListA, stIdListB As Integer

    For Each la In listA
        stidListA = la.StudentId

        For n = 0 To dtListB.Rows.Count - 1 Step 1
            stIdListB = dtListB.Rows(n)("StudentId")
            If stIdListB <> stidListA Then
    dtListB.Rows.Add(New Object() {la.StudentId, la.AssignedId, la.TimeSheetId, 0})
            End If
        Next
    Next

I'm not sure why the error is thrown :

Exception of type 'System.OutOfMemoryException' was thrown.

dtListB.Rows.Add(New Object() {la.StudentId, la.AssignedId, la.TimeSheetId, 0})

Any suggestion? Thanks.

+1  A: 

You are iterating with dtListB.Rows and inserting into dtListB.Rows. It is increasing the Count and just looping for an indeterminate amount of time.

Daniel A. White
Yes, you're right. I have to move dtListB.Rows.Add out of the its loop.
Narazana
A: 

The problem is that you aren't really checking if StudentId of ListA doesn't exist in dtListB. What your code actually does is it compares EVERY element in dtListB with the current element from ListA and if in case they are not the same, it adds a new row to dtListB. So assume you have the following lists:

ListA = { 3, 4 };
dtListB = { 1, 2, 3 };

The first iteration for ListA, value is 3.

Check: (3 <> 1) and add '3' to dtListB (dtListB = { 1, 2, 3, 3 })
Check: (3 <> 2) and add '3' to dtListB (dtListB = { 1, 2, 3, 3, 3 })
Check: (3 <> 3) and don't do anything.
(Since the list has grown, you have two more iterations)

For the second iteration for ListA with value 4 you will insert it 5 times for every element of the existing array you compare with, and get the resulting list: { 1, 2, 3, 3, 3, 4, 4, 4, 4, 4 }. Obviously that's not the result you are expecting, and you probably have larger lists and run out of memory.

I would suggest keeping a Boolean flag itemFound when looping through dtListB. Set it to False before the loop and if a matching item is encountered, set it to True. After the loop, check if itemFound is False and if so, add the item to the list. This probably isn't valid VB syntax, but you get the idea:

For Each la In listA
    stidListA = la.StudentId

    Dim itemFound as Boolean = False

    For n = 0 To dtListB.Rows.Count - 1 Step 1
        stIdListB = dtListB.Rows(n)("StudentId")
        If stIdListB <> stidListA Then
            itemFound = True
            Break //(is there Break in VB?)
        End If
    Next

    If Not itemFound Then
        dtListB.Rows.Add(New Object() {la.StudentId, la.AssignedId, la.TimeSheetId, 0})
    End If
Next
Yakimych
Yes, declaring a variable for item found is easy for manipulating the datatable later on. Anyway, there's no Break but Exit For in VB.NET.
Narazana