Menu

Collection cache

2005-02-04
2013-03-07
  • victor Saquicela

    Hi,

    You have following code:

    Public Sub CopyCollections()
            Dim t, iEnumerableType, iListType, iDicType As Type
            Dim coll, obj As Object
            Dim il As IList
            Dim id As IDictionary
            Dim f, fields() As FieldInfo
            Dim value As Object

            'We must precopy this collection into the collection copy
            'A simple assignment would just copy a reference to the colletion, while
            'we need to copy the collection itself, so that adding/removing elements
            'of the original won't effect the copy
            m_collectionCollection = New Specialized.HybridDictionary

            t = m_object.GetObjectType
            fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public)
            For Each f In fields
                iListType = f.FieldType.GetInterface("IList", True)
                iDicType = f.FieldType.GetInterface("IDictionary", True)
                'iEnumerableType = f.FieldType.GetInterface("IEnumerable", True)
                If Not iListType Is Nothing OrElse Not iDicType Is Nothing Then
                    Dim ICloneType As Type = f.FieldType.GetInterface("ICloneable", True)
                    If Not ICloneType Is Nothing Then
                        'Getting the ICloneable interface from the object.
                        Dim IClone As ICloneable = CType(f.GetValue(m_object), ICloneable)
                        'We use the clone method to set the new value to the field.
                        coll = IClone.Clone()
                    Else
                        'If the field doesn't support the ICloneable interface then just set it.
                        coll = Activator.CreateInstance(f.FieldType)
                        'need to copy references one-by-one
                        If Not iListType Is Nothing Then
                            il = CType(coll, IList)
                            For Each obj In f.GetValue(m_object.GetSourceObject)
                                il.Add(obj)
                            Next
                        Else
                            id = CType(coll, IDictionary)
                            For Each de As DictionaryEntry In f.GetValue(m_object.GetSourceObject)
                                id.Add(de.Key, de.Value)
                            Next
                        End If
                    End If
                    m_collectionCollection.Add(f.Name, coll)
                End If
            Next
        End

    If I have define collection but this collection isn't initialized, it is a mistake. I think that in lines:

    'Getting the ICloneable interface from the object.
                        Dim IClone As ICloneable = CType(f.GetValue(m_object), ICloneable)
                        'We use the clone method to set the new value to the field.
                        coll = IClone.Clone()

    will be have a try and catch or verify.

    Rollback of the collection is incorrect, don't rollback.

     
    • Richard Banks

      Richard Banks - 2005-02-06

      Hi Victor,

      Thanks for the notice.  I've fixed the code and tested it and you should be OK now (obviosuly you'll need to get the latest version from CVS)

       
    • victor Saquicela

      Hi.

      It is correct. But, The rollback of collection isn't correct. I have a following structure:
      A--OneToMany--B
      B--OneToOne--C

      If I delete a object B of the collection the object A, add Object B to collection the object A, then I execute rollback of the transaction. The rollback of the database is correct, but The rollback of the cache is incorrect, because the collection with the object added don't deleted and the object deleted don't restore.

      I think that can be because, I am using an inherits of the collection to bind a DataGrid. (I am using a example to bind collection to datagrid).

      Saludos

      Victor

       
      • Richard Banks

        Richard Banks - 2005-02-07

        Hi Victor,

        Would you be able to create a unit test that duplicates the error? I'm not quite sure what you are doing and a unit test will really help me debug it.

        - Richard.

         
    • victor Saquicela

      Hi.

      I have a following structure:

      <class name="Cuenta" table="cuenta" database="erp" namespace="Finanzas.GestionBancosCaja">
              <attribute name="CodigoCuenta" column="codigocuenta" find="true" key="primary" />
              <attribute name="Numero" column="numero" />
              <attribute name="Descripcion" column="descripcion" />
              <attribute name="Saldo" column="saldo" />
              <attribute name="TipoEstado" />       
              <attribute name="CodigoTipoEstado" column="codigotipoestado" />
              <attribute name="Transacciones"/>
              <attribute name="CreatedDate" column="CreatedDate" timestamp="true" />
              <attribute name="ModifiedDate" column="ModifiedDate" timestamp="true" />
          </class>

      <class name="Transaccion" table="transaccion" database="erp" namespace="Finanzas.GestionBancosCaja">
              <attribute name="CodigoTransaccion" column="codigotransaccion" find="true" key="primary" />
              <attribute name="Fecha" column="fecha" />
              <attribute name="Valor" column="valor" />
              <attribute name="Descripcion" column="descripcion" />
              <attribute name="Saldo" column="saldo" />       
              <attribute name="Cuenta"/>
              <attribute name="CodigoCuenta" column="codigocuenta" />       
              <attribute name="CreatedDate" column="CreatedDate" timestamp="true" />
              <attribute name="ModifiedDate" column="ModifiedDate" timestamp="true" />
          </class>

          <association fromClass="Finanzas.GestionBancosCaja.Cuenta" toClass="Finanzas.GestionBancosCaja.Transaccion" cardinality="oneToMany"
              target="transacciones" retrieveAutomatic="lazy" deleteAutomatic="false" saveAutomatic="false"
              inverse="false">
              <entry fromAttribute="CodigoCuenta" toAttribute="CodigoCuenta" />
          </association>

      ****************************************
      now I am need execute the next instruction to view collection in a datagrid:

      dim c as Cuenta= new Cuenta
      c.codigoCuenta=1
      c.find(c)

      datagrid.dataSource=c.transacciones

      ''It is correct!!!!!! I am assume that has data in my database (Cuenta have 4 transaciones)

      ''But now,
      ''Begin transaction

      dim t as Transaccion = new Transaccion
      dim t1 as Transaccion= new Transaccion
      .......

      c.transacciones.add(t)
      c.transacciones.add(t2)

      c.transacciones(1).delete

      if I execute commit, it is correct.

      If I execute rollback, the collection is the same. I think that the collection will be restored to initial state.
      *****************************************
      the code of the transaction and cuenta is the following:

      ' Modelo esttico

      Imports AToMSFramework
      Imports Finanzas.GestionBancosCaja
      Imports Finanzas.GestionCobros
      Imports Finanzas.GestionPagos
      Namespace GestionBancosCaja

          ' Clase base para crear cuentas bancarias o caja
          Public Class Cuenta
              Inherits CPersistentObject

              ' Clave unica de la cuenta
              Private _codigoCuenta As Integer

              ' Descripcion corta de la cuenta
              Private _descripcion As String

              ' Numero de la cuenta (si es bancaria, vacio si es caja)
              Private _numero As String

              ' Saldo actual de la cuenta
              Private _saldo As Decimal

              'Estado en la que puede estar una cuenta
              Private _tipoEstado As ERP.TipoEstado
              Private _codigoTipoEstado As Integer

              'Listado de pagos de una cuenta
              Private _pagos As System.Collections.ArrayList

              'Listado de Cobros de una Cuenta
              Private _cobros As System.Collections.ArrayList

              'Listado de transacciones de una cuenta
              Private WithEvents _transacciones As TransaccionC

              ' Constructor
              Public Sub New()
                  MyBase.New()
                  _transacciones = New TransaccionC
                  _transacciones.ContainerObject = Me

              End Sub
              Property Transacciones() As CPersistentCollection
                  Get
                      Return _transacciones
                  End Get
                  Set(ByVal Value As CPersistentCollection)
                      If Not CPersistentObject.Equals(_transacciones, Value) Then
                          _transacciones = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property
              ' Propiedad para manipular el _codigoCuenta
              Public Property CodigoCuenta() As Integer
                  Get
                      Return _codigoCuenta
                  End Get

                  Set(ByVal Value As Integer)
                      If _codigoCuenta <> Value Then
                          _codigoCuenta = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para manipular el _descripcion
              Public Property Descripcion() As String
                  Get
                      Return _descripcion
                  End Get

                  Set(ByVal Value As String)
                      If _descripcion <> Value Then
                          _descripcion = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para manipular el _numero
              Public Property Numero() As String
                  Get
                      Return _numero
                  End Get

                  Set(ByVal Value As String)
                      If _numero <> Value Then
                          _numero = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para manipular el atributo _saldo
              Public Property Saldo() As Decimal
                  Get
                      Return _saldo
                  End Get

                  Set(ByVal Value As Decimal)
                      If _saldo <> Value Then
                          _saldo = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              'Propiedad para manipular el objeto tipo estado
              Public Property TipoEstado() As ERP.TipoEstado
                  Get
                      If _tipoEstado Is Nothing Then
                          _tipoEstado = New ERP.TipoEstado
                          _tipoEstado.CodigoTipoEstado = Me._codigoTipoEstado
                          _tipoEstado.Retrieve(_tipoEstado)
                      End If
                      Return _tipoEstado
                  End Get
                  Set(ByVal Value As ERP.TipoEstado)
                      If Not CPersistentObject.Equals(_tipoEstado, Value) Then
                          _tipoEstado = Value
                          CodigoTipoEstado = _tipoEstado.CodigoTipoEstado
                          SetDirtyFlag()
                      End If
                  End Set
              End Property
              'Propiedad para manipular el atributo _codigoTipoEstado
              Public Property CodigoTipoEstado() As Integer
                  Get
                      If _tipoEstado Is Nothing Then
                          Return _codigoTipoEstado
                      Else
                          Return _tipoEstado.CodigoTipoEstado
                      End If
                  End Get
                  Set(ByVal Value As Integer)
                      If Not _tipoEstado Is Nothing Then
                          If _tipoEstado.CodigoTipoEstado <> Value Then
                              _tipoEstado.CodigoTipoEstado = Value
                              SetDirtyFlag()
                          End If
                      End If
                      _codigoTipoEstado = Value
                  End Set
              End Property

              ' Disminuir el saldo
              Public Function decrementarCantidad(ByVal c As Integer) As Transaccion
                  Me._saldo = Me._saldo - c
                  'Generar la transaccion respectiva
                  Dim t As Transaccion = New Transaccion
                  t.CodigoTransaccion = ERP.GestorSerial.getSerial("Transaccion")
                  t.Valor = c
                  t.Saldo = Me.Saldo 'Ultimo saldo se asigana a transaccion
                  t.Descripcion = "Ingreso en la cuenta"
                  t.Fecha = Now
                  t.Cuenta = Me
                  Me.agregarTransaccion(t) 'Agregar Transaccion a la cuenta
                  Return t
              End Function

              ' Incrementar el saldo de la cuenta
              Public Function incrementarCantidad(ByVal c As Decimal) As Transaccion
                  Me._saldo = Me._saldo + c
                  'Generar la transaccion respectiva
                  Dim t As Transaccion = New Transaccion
                  t.CodigoTransaccion = ERP.GestorSerial.getSerial("Transaccion")
                  t.Valor = c
                  t.Saldo = Me._saldo 'Ultimo saldo se asigana a transaccion
                  t.Descripcion = "Ingreso en la cuenta"
                  t.Fecha = Now
                  t.Cuenta = Me
                  Me.agregarTransaccion(t) 'Agregar Transaccion a la cuenta
                  Return t
              End Function

              ' Permite agregar una nueva transaccion a la coleccion que posee la cuenta
              Public Sub agregarTransaccion(ByVal t As Transaccion)
                  Me._transacciones.Add(t)
              End Sub

              ' Cambiar de estado un cuenta (Puede estar activada o desactivada).
              Public Sub cambiarEstado(ByVal e As ERP.TipoEstado)
                  Me.TipoEstado = e
              End Sub

              ' Recupera las transacciones asociadas a la cuenta.
              Public Function listadoTransacciones() As CPersistentCollection
                  Return Me._transacciones
              End Function
              Public Overrides Function getNewObject() As CPersistentObject
                  Return New Cuenta
              End Function
              Public Overrides Function IsValid() As Boolean
                  Return True
              End Function
          End Class ' END CLASS DEFINITION Cuenta

      End Namespace ' GestionBancosCaja

      ' Modelo esttico
      Imports AToMSFramework

      Namespace GestionBancosCaja

          Public Class TransaccionC
              Inherits CPersistentCollection
              Public Overloads Sub Add(ByVal ol As Transaccion)
                  MyBase.Add(ol)
              End Sub

              Default Public Shadows ReadOnly Property Item(ByVal index As Integer) As Transaccion
                  Get
                      Return CType(list.Item(index), Transaccion)
                  End Get
              End Property

              Public Overrides ReadOnly Property AllowEdit() As Boolean
                  Get
                      Return True
                  End Get
              End Property

              Public Overrides Function AddNew() As Object
                  Dim ol As New Transaccion
                  If Not Me.ContainerObject Is Nothing Then
                      'Assign the order header reference if possible
                      'Dim p As Transaccion = Me.ContainerObject
                      ol.Cuenta = Me.ContainerObject
                  End If
                  list.Add(ol)
                  Return ol
              End Function

              Public Overrides ReadOnly Property AllowNew() As Boolean
                  Get
                      Return Not Me.ContainerObject Is Nothing
                  End Get
              End Property

              Public Overrides ReadOnly Property AllowRemove() As Boolean
                  Get
                      Return True
                  End Get
              End Property

          End Class

          ' Clase base para registro de movimientos en las diferentes cuentas.
          Public Class Transaccion
              Inherits CPersistentObject
              ' OID del objeto transaccion
              Private _codigoTransaccion As Integer

              ' Fecha en la que se realiza la transaccion
              Private _fecha As Date

              ' Cantidad que implica la transaccionn.
              Private _valor As Decimal

              ' Saldo despues de incrementar o decrementar el saldo de la cuenta. Es mas informativo, para no tener que volver a recalcular el saldo en cierta fecha.
              Private _saldo As Decimal

              ' Descripcion corta de la transaccion.
              Private _descripcion As String

              ' Cuenta a la que pertenece
              Private _cuenta As Cuenta
              Private _codigoCuenta As Integer

              ' Constructor
              Public Sub New()

              End Sub

              ' Propiedad para acceder al atributo _codigoTransaccion
              Public Property CodigoTransaccion() As Integer
                  Get
                      Return _codigoTransaccion
                  End Get

                  Set(ByVal Value As Integer)
                      If _codigoTransaccion <> Value Then
                          _codigoTransaccion = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para acceder al atributo _fecha
              Public Property Fecha() As Date
                  Get
                      Return _fecha
                  End Get

                  Set(ByVal Value As Date)
                      If _fecha <> Value Then
                          _fecha = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para acceder al atributo _valor
              Public Property Valor() As Decimal
                  Get
                      Return _valor
                  End Get

                  Set(ByVal Value As Decimal)
                      If _valor <> Value Then
                          _valor = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para acceder al atributo _saldo
              Public Property Saldo() As Decimal
                  Get
                      Return _saldo
                  End Get

                  Set(ByVal Value As Decimal)
                      If _saldo <> Value Then
                          _saldo = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property

              ' Propiedad para acceder al atributo _descripcion
              Public Property Descripcion() As String
                  Get
                      Return _descripcion
                  End Get

                  Set(ByVal Value As String)
                      If _descripcion <> Value Then
                          _descripcion = Value
                          SetDirtyFlag()
                      End If
                  End Set
              End Property
              'Propiedad para manipular el objeto Cuenta
              Public Property Cuenta() As Cuenta
                  Get
                      If _cuenta Is Nothing Then
                          _cuenta = New Cuenta
                          _cuenta.CodigoCuenta = Me._codigoCuenta
                          _cuenta.Retrieve(_cuenta)
                      End If
                      Return _cuenta
                  End Get
                  Set(ByVal Value As Cuenta)
                      If Not CPersistentObject.Equals(_cuenta, Value) Then
                          _cuenta = Value
                          CodigoCuenta = _cuenta.CodigoCuenta
                          SetDirtyFlag()
                      End If
                  End Set
              End Property
              'Propiedad para manipular el atributo _codigoCuenta
              Public Property CodigoCuenta() As Integer
                  Get
                      If _cuenta Is Nothing Then
                          Return _codigoCuenta
                      Else
                          Return _cuenta.CodigoCuenta
                      End If
                  End Get
                  Set(ByVal Value As Integer)
                      If Not _cuenta Is Nothing Then
                          If _cuenta.CodigoCuenta <> Value Then
                              _cuenta.CodigoCuenta = Value
                              SetDirtyFlag()
                          End If
                      End If
                      _codigoCuenta = Value
                  End Set
              End Property
              Public Overrides Function getNewObject() As CPersistentObject
                  Return New Transaccion
              End Function
              Public Overrides Function IsValid() As Boolean
                  Return True
              End Function

          End Class ' END CLASS DEFINITION Transaccion

      End Namespace ' GestionBancosCaja

      Saludos

      Victor.

       
    • Richard Banks

      Richard Banks - 2005-02-07

      Your code was this:

      'Begin transaction
      dim t as Transaccion = new Transaccion
      dim t1 as Transaccion= new Transaccion
      .......
      c.transacciones.add(t)
      c.transacciones.add(t2)
      c.transacciones(1).delete

      Since it's not in the sample code do I assume that you are doing a CPersistenceBroker.StartTransaction() call before you add/delete items in the collection?

      You might want to look at the CheckCacheAfterRollback4 unit test in CVS (in InheritedClasses/AtomsFrameworkTests.vb) since it does both the add and delete from the collection during a transaction and it works properly.

       
    • Nobody/Anonymous

      Hi.

      I am doing a CPersistenceBroker.StartTransaction()

      dim t as Transaccion = new Transaccion 
      dim t1 as Transaccion= new Transaccion 
      ....... 
      c.transacciones.add(t) 
      c.transacciones.add(t2) 
      c.transacciones(1).delete 

      now, if I execute rollBack. The cache of the collection is incorrect. Because the collection don't have the same objects.

       
    • Nobody/Anonymous

      The unique diference is that I am using inherits of the CPersistentCollection how container.

      Saludos

      Victor

       
      • Richard Banks

        Richard Banks - 2005-02-08

        I don't think that should make a difference since I am only looking for objects that implement IList or IDictionary.  If you inherit the CPersistentCollection then you will have an object that implements IList.

        Can you do some debugging for me?

        In CCacheEntry.vb set breaks at CopyCollections() and at RestoreCollections().

        What _should_ happen is that when the transaction starts the collections in the object should be copied into new objects and placed in a "collection of collections" called m_collectionCollection.

        When the transaction aborts RestoreCollections should copy the collections from m_collectionCollection over the collections in the object they came from.

        If you can verify a few things it will help

        1.  That the collections are all being correctly copied in the first place.  (Look at f.name to see what field is being copied).
        2.  That the restoreCollections method is being called
        3.  That the collections are being correctly copied back out of m_collectionCollection.

        I appreciate the help on this one

        - Richard.

         
    • victor Saquicela

      Hi.

      I have a few questions?

      First:
      My example is when a collection is empty.

      When execute the method CopyCollection in a code:
      m_collectionCollection.Add(f.Name, coll) is correct.

      The value of the  m_collectionCollection.count=3.

      Now if I execute rollback of the transsaction, the code : RestoreCollections()  is called.

      In the method AbortChanges the instructions:
      For Each ck In al
                  MyBase.Remove(ck)
      Next

      also are called. That is to say, the remove is executed.

      Now, My object continues with the information in the collection, the previous one is not restored.

      The following code in RestoreCollection:
      If Not iListType Is Nothing OrElse Not iDicType Is Nothing Then
                      'We must restore this collection from the collection copy
                      'Just use a straight value assignment - no need to worry about cloning
                      f.SetValue(m_object.GetSourceObject, m_collectionCollection.Item(f.Name))
                  End If

      It is never executed (f.SetValue), Why ???

      Why to do the cache of all the collecciones of the objects in cache. I think that will be alone of the objects that are used in the transaction.

      Saludos

      Victor

       
      • Richard Banks

        Richard Banks - 2005-02-09

        >The value of the m_collectionCollection.count=3.

        This indicates that there were 3 collection objects that were copied.  This would mean that the Cuenta private fields:
        Private _pagos As System.Collections.ArrayList
        Private _cobros As System.Collections.ArrayList
        Private WithEvents _transacciones As TransaccionC

        were all copied correctly.

        >In the method AbortChanges the instructions:
        >For Each ck In al
        >MyBase.Remove(ck)
        >Next

        This code is actually removing objects from the cache that were added during the transaction.  In other words, if you begin a transaction, create and save an object and then abort the transaction then the object you created should be removed from the cache.  This code won't affect collections of individual objects

        >The following code in RestoreCollection:
        >If Not iListType Is Nothing OrElse Not iDicType Is Nothing Then
        >'We must restore this collection from the collection copy
        >'Just use a straight value assignment - no need to worry about cloning
        >f.SetValue(m_object.GetSourceObject, m_collectionCollection.Item(f.Name))
        >End If

        If RestoreCollections is called but f.SetValue() is never called then none of the fields for the object implement the IList or IDictionary interface.

        I assume that m_object.GetSourceObject is the same object that the collections were copied from in CopyCollections().  I also assume that the m_collectionCollection.Count value is still 3.

        If you set a break on the line
        iListType = f.FieldType.GetInterface("IList", True)
        in RestoreCollections() and then check the value of f.name you should see that the _pagos, _cobros and _transacciones fields are all checked to see if they implement the IList interface (iListType should not be nothing when the call completes).  If that doesn't happen can you let me know what you find in the debug session.

        By the way, I noticed that in class Cuenta you have

        > Private WithEvents _transacciones As TransaccionC

        But that the property exposes a different type

        > Property Transacciones() As CPersistentCollection

        It might be a good idea to change the property type to match that of the internal object

        I hope we get to the bottom of this soon

        - Richard.

         
    • victor Saquicela

      Hi.

      The problem is that in the following code:

      Public Sub RestoreCollections()
              Dim t, iEnumerableType, iListType, iDicType As Type
              Dim f, fields() As FieldInfo
              t = m_object.GetObjectType
              fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public)
              For Each f In fields
                  iListType = f.FieldType.GetInterface("IList", True)
                  iDicType = f.FieldType.GetInterface("IDictionary", True)
                  'iEnumerableType = f.FieldType.GetInterface("IEnumerable", True)
                  If Not iListType Is Nothing OrElse Not iDicType Is Nothing Then
                      'We must restore this collection from the collection copy
                      'Just use a straight value assignment - no need to worry about cloning
                      f.SetValue(m_object.GetSourceObject, m_collectionCollection.Item(f.Name))
                  End If
              Next
          End Sub

      the atribute fields does not have the collection name, f.name doesn't have _transacciones, _pagos, _cobros.

      The problem is that in the code:
      t = m_object.GetObjectType

      m_object  does not have the object that  possesses the collections.

      This means that in the method AbortChanges of CCacheEntry doesn't have my object that possesses the collections or it does not fulfill certain conditions.

      In the next code in method AbortChanges:

      For Each x In Me
                  ce = x.Value
                  'Lets cancel deletes first - just means resetting transaction to None
                  If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted AndAlso ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then
                      ce.TransactionType = CCacheEntry.CacheTransaction.None
                      ce.RestoreCollections()
                  End If
                  'Now look for cache entries to be saved and restore them
                  If ce.TransactionType = CCacheEntry.CacheTransaction.Saved AndAlso ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then
                      ce.RestoreObject()
                      ce.RestoreCollections()
                      ce.TransactionType = CCacheEntry.CacheTransaction.None
                  End If
              Next

      The instructions are never executed inside the sentence IF( if ce is an object with collections).

      Which they are the conditions in order that these instructions are executed.

      Saludos

      victor

       
      • Richard Banks

        Richard Banks - 2005-02-10

        >The problem is that in the code:
        >t = m_object.GetObjectType
        >m_object does not have the object that possesses the collections.

        m_object is an instance of the interface IPersistableObject and is designed to wrap around the actual object being saved.  It can be either a CInjectedObject or a CPersistentObject depending on wether the object inherits from CPeristentObject or not.

        the GetObjectType property will return the type of the object that m_object is wrapping.  If you have a look at m_object.GetObjectType.Name you should get a value of "Cuenta"

        Now something occurred to me when you said the code in the IF statements didn't execute.   The code to restore the collections will only execute if the object has been saved or deleted inside a transaction.
        There is no code to roll back the changes if the object is dirty (ie modified) but not yet saved.

        For example
        broker.StartTransaction()
        myObject.Property = NewValue
        myObject.Save()
        broker.Rollback()

        will restore myObject correctly, while

        broker.StartTransaction()
        myObject.Property = NewValue
        broker.Rollback()

        will leave myObject.Property in it's current (modified) state - however the cached copy of the object should still be in it's original state.

        So I went and wrote a unit test that changed an object, aborted the transaction and checked the cached copy of the object.

        I found that when the cache returned a copy of an object to the application it was only doing a shallow copy.  Normally this is perfectly fine, however because collections are copied by reference, changing the collection in the application changed it in the cache.

        I've just committed some changes on the v2_0 branch in CVS to fix the problem, and hopefully you will now be OK.

        By the way, I would not recommend getting the code from the HEAD branch just at the moment as it's a bit messy and some parts are broken while I work on many-to-many associations.

        - Richard.

         
    • Nobody/Anonymous

      Hi.

      My problem was that was not save the principal object and save only objects the collections.

      but, now all right.

      I do not need to unload the last cvs.

      Saludos

      Victor

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.