|
-
Feb 18th, 2008, 10:10 AM
#1
Thread Starter
Frenzied Member
[RESOLVED] [2005] items values changing in list when new item added
Description:
First the explaination of a I have a function that I’ve created. It basically uses reflection to create and return a particular type. Whatever I pass in is what I will get back and the function is complete generic. Heres my two senrios. I also use a class called SafeDataReader, which all it does is simple implement the IDataReader interface and does some behind the scenes things so as to not return a DBNull.Value, if that’s what was returned from the read, but the value you except ie you want a string you get an empty string not a DBNul value. Ok here we go, if I don’t make any sense let me know.
1. I have a class call Abc. It has a property called Name. The constructor is like so… Public Sub New(ByVal dr As SafeDataReader)
2. Now I have a class called AbcXyzManager that inherits from a base class that I’ve created and has a function with the following signature. Protected Function FetchDataObjects(Of T, C As List(Of T))(ByVal objectToCreate As Type, ByVal sqlStatement As String, ByVal params As Core.CSSIDbParameterCollection, Optional ByVal cmdType As CommandType = CommendType.Text) As C
3. Now in a function in the AbcXyzManager class called GetAbcList I setup the sql statement and parameters this function is going to return a List(Of Abc). So the signature of the inherited function would look like so Return FetchDataObjects(Of Abc, List(Of Abc))(GetType(Abc), sql, params).
4. What the code below runs it returns a list of Abc that has 3 items each item has different values.
5. This all works just fine item 1’s Abc.Name = Test1, 2’s Abc.Name = Test2, and 3’s Abc.Name = Test3.
6. Now for the kicker.
7. I do the same exact thing only this time I have a class called Xyz, might have different properties, but the same type of constructor.
8. In the AbcXyzManager I have a function called GetXyzList again I setup everything and then return a List of type Xyz.
9. Again I use the FetchDataObjects the only difference this time is it’s of type Xyz and the list is of type Xyz. So the object that needs to be created is Xyz.
10. When the code runs and reads data creates an instance of Xyz and adds it to the list, everything works fine… Until it reads the next record.
11. When it reads the record, instanciates the Xyz object and calls the constructor everything works as it should. I read the records and setup whatever properties/members need to be in the Xyz object.
12. Now for the real big kicker… Once the newly created object is added to the list. If I look at the list so far only two Xyz objects have been added… you would think that these two items of xyz would have different values for the properties… ie lets say there are two properties Name and Number. Name should be Test1, Number should be 1, because that’s what was read from the first record. Now the second item should have a Name property value of Test2 and a Number property value of 2, because again that’s what was read from the second record. However, if I look at the first item the Name value is Test2 and the Number value is 2. It’s as though it’s over writing the previous item(s).
I’ve stepped through my code and watched each and ever value be set each time a record was read. Each time the values are different and prior to adding the newly created Xyz object to the list the first item has different values. As soon as the new Xyz object is added to the list thouh all previous items in the list take on the values from that Xyz object. Again I use the same code for creating a list of type Abc and it works perfectly fine. Here’s the code of the base class function. The problem occurs when it runs the following code.
vb Code:
Do While dr.Read
retval.Add(Activator.CreateInstance(objectToCreate, New Object() {dr}))
Loop
vb Code:
Protected Function FetchDataObjects(Of T, C As List(Of T))(ByVal objectToCreate As Type, _
ByVal sqlStatement As String, _
ByVal params As DbParameter(), _
Optional ByVal cmdType As CommandType = CommandType.Text) _
As C
Dim retval As List(Of T) = Nothing
Try
m_Cnn = DbProviderFactories.GetFactory(m_Provider).CreateConnection
m_Cnn.ConnectionString = m_CnnStr
m_Cnn.Open()
If m_Cnn.State = ConnectionState.Open Then
m_Cmd = m_Cnn.CreateCommand
m_Cmd.CommandText = sqlStatement
m_Cmd.CommandType = cmdType
If params IsNot Nothing AndAlso params.Count > 0 Then
m_Cmd.Parameters.AddRange(params)
End If
Try
Using dr As New Data.Core.SafeDataReader(m_Cmd.ExecuteReader)
Try
retval = New List(Of T)
Do While dr.Read
retval.Add(Activator.CreateInstance(objectToCreate, New Object() {dr}))
Loop
Catch dbEx As DbException
Throw dbEx
Catch ex As Exception
Throw ex
End Try
End Using
Catch dbEx As DbException
Throw dbEx
Catch ex As Exception
Throw ex
End Try
End If
Catch ex As Exception
Throw ex
Finally
If m_Adapter IsNot Nothing Then
m_Adapter.Dispose()
m_Adapter = Nothing
End If
If m_Cmd IsNot Nothing Then
m_Cmd.Dispose()
m_Cmd = Nothing
End If
If m_Cnn IsNot Nothing Then
'Place closing in try block as the connection
'object may still be disposed.
Try
m_Cnn.Close()
m_Cnn.Dispose()
Finally
m_Cnn = Nothing
End Try
End If
End Try
Return retval
End Function
-
Feb 18th, 2008, 11:08 AM
#2
Re: [2005] items values changing in list when new item added
The problem appears clear: Objects are never actually added to the list, all that is ever added is a reference to an object. In this case, what is being added is just copies of references to new objects, rather than references to new objects. You pointed out where the problem is occuring, and I managed to overlook that part and identify where the problem was occuring by looking at the code, so your previous statement matches up with what I was seeing. However, you don't show what is happening in that Add argument which is causing the trouble.
My usual boring signature: Nothing
 
-
Feb 18th, 2008, 11:39 AM
#3
Thread Starter
Frenzied Member
Re: [2005] items values changing in list when new item added
sorry shaggy, i'm not i understand how i'm not showing what is happening in the add argument. unless you're talking about the Activator.CreateInstance. in either case here's something else that I tried. returned a datatable and looped through the rows creating a new instance of the object and adding it to a list. again same problem
vb Code:
Dim lst As New List(Of Xyz) For Each row In tbl.Rows Dim obj As New Xyz(row(0), row(1), row(2)) lst.Add(obj) Next
as soon as the second record is read, the object is create and added, the previous item in the list changes
-
Feb 18th, 2008, 12:29 PM
#4
Thread Starter
Frenzied Member
Re: [2005] items values changing in list when new item added
here's code i threw together quick that does basically the same thing only it's not reading from a database and i'm only adding 7 items. this works as it should
vb Code:
Module Module1 Sub Main() For Each itm As Test In Testing(Of Test, List(Of Test))(GetType(Test)) Console.WriteLine("{0} {1}", itm.Name, itm.Number) Next Console.Read() End Sub Private Function Testing(Of T, C As List(Of T))(ByVal obj As Type) As C Dim lst As New List(Of T) For i As Integer = 1 To 7 lst.Add(Activator.CreateInstance(obj, New Object() {"test" + i.ToString, i})) Next Return lst End Function End Module Public Class Test Private m_name As String Private m_number As Int32 Public Property Name() As String Get Return m_name End Get Set(ByVal value As String) m_name = value End Set End Property Public Property Number() As Int32 Get Return m_number End Get Set(ByVal value As Int32) m_number = value End Set End Property Public Sub New(ByVal n1 As String, ByVal n2 As Int32) m_name = n1 m_number = n2 End Sub End Class
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|