Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26911 Modified Files: CCacheEntry.vb CClassMap.vb CInjectedObject.vb CInjectedObjects.vb CPersistenceBroker.vb CPersistentObject.vb IPersistentObject.vb Log Message: More changes to persist non-inherited objects. Object hierarchies are now persistable Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.64 retrieving revision 1.65 diff -u -d -r1.64 -r1.65 --- CPersistenceBroker.vb 14 Oct 2004 05:25:02 -0000 1.64 +++ CPersistenceBroker.vb 15 Oct 2004 06:42:56 -0000 1.65 @@ -394,7 +394,7 @@ ' All objects are loaded to the cache regardless of applications cache usage m_cache.Add(targetobj) End If - obj.setAttributeValue(udamap.Target, targetobj) + obj.SetAttributeValue(udamap.Target, targetobj.GetSourceObject) If Not targetobj.AssociationsLoaded Then retrievePrivateObject(targetobj, conn, False, False) Else @@ -426,7 +426,7 @@ targetobj.IsDirty = False targetobj.OriginalCacheKey = New CCacheKey(targetobj) End If - obj.setAttributeValue(udamap.Target, targetobj) + obj.SetAttributeValue(udamap.Target, targetobj.GetSourceObject) End If Else 'Object doesn't exist - let's create it @@ -449,7 +449,7 @@ targetobj.IsDirty = False targetobj.OriginalCacheKey = New CCacheKey(targetobj) End If - obj.setAttributeValue(udamap.Target, targetobj) + obj.SetAttributeValue(udamap.Target, targetobj.GetSourceObject) End If End If End If @@ -475,7 +475,12 @@ 'Need to determine if new object is already in the collection '(prevents duplicates when multiple one-to-many associations exist) gotValue = False - For Each tmpObj In col + For Each tmpColObj As Object In col + If Not tmpColObj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + tmpObj = LocateOrCreateInjObject(tmpColObj) + Else + tmpObj = tmpColObj + End If If tmpObj.Equals(targetobj) Then gotValue = True End If @@ -489,7 +494,7 @@ targetobj.OriginalCacheKey = New CCacheKey(targetobj) End If If targetobj.AssociationsLoaded Then - col.Add(targetobj) + col.Add(targetobj.GetSourceObject) 'the object is found and added to the collection ' Exit For End If @@ -511,7 +516,12 @@ 'Need to determine if new object is already in the collection '(prevents duplicates when multiple one-to-many associations exist) gotValue = False - For Each tmpObj In col + For Each tmpColObj As Object In col + If Not tmpColObj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + tmpObj = LocateOrCreateInjObject(tmpColObj) + Else + tmpObj = tmpColObj + End If If tmpObj.Equals(targetobj) Then gotValue = True End If @@ -524,7 +534,7 @@ targetobj.OriginalCacheKey = New CCacheKey(targetobj) End If If targetobj.AssociationsLoaded Then - col.Add(targetobj) + col.Add(targetobj.GetSourceObject) End If End If End If @@ -600,7 +610,7 @@ End If Value.IsDirty = False Value.OriginalCacheKey = New CCacheKey(Value) - obj.setAttributeValue(udaMap.Target, Value) + obj.setAttributeValue(udaMap.Target, Value.GetSourceObject) gotValue = True End If End If @@ -627,7 +637,7 @@ End If Value.IsDirty = False 'After populating a new object Value.OriginalCacheKey = New CCacheKey(Value) - obj.setAttributeValue(udaMap.Target, Value) + obj.setAttributeValue(udaMap.Target, Value.GetSourceObject) End If End If ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then @@ -695,9 +705,6 @@ conn.startTransaction() conn.AutoCommit = False savePrivateObject(obj, conn) - 'If m_useCache Then - ' m_cache.Add(obj) 'Add to the cache - 'End If conn.commit() Catch ex As Exception conn.rollback() @@ -784,7 +791,7 @@ ''' [rbanks] 16/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - Public Sub deleteObject(ByVal obj As CPersistentObject) + Public Sub deleteObject(ByVal obj As IPersistableObject) Call deleteObject(obj, False) End Sub @@ -800,11 +807,11 @@ ''' [rbanks] 16/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - Public Sub deleteObject(ByVal obj As CPersistentObject, ByVal deleteSuperClass As Boolean) + Public Sub deleteObject(ByVal obj As IPersistableObject, ByVal deleteSuperClass As Boolean) SyncLock GetType(CPersistenceBroker) Dim cm As CClassMap Dim x As DeleteException - cm = obj.getClassMap(obj) + cm = obj.getClassMap Dim conn As _CConnection conn = cm.RelationalDatabase.getConnection(Nothing) conn.startTransaction() @@ -835,7 +842,7 @@ ''' [rbanks] 16/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - Public Sub deleteCachedObject(ByVal obj As CPersistentObject) + Public Sub deleteCachedObject(ByVal obj As IPersistableObject) If m_useCache Then m_cache.Remove(obj) End If @@ -858,9 +865,9 @@ ''' child objects are deleted ''' </history> '''----------------------------------------------------------------------------- - Private Sub deletePrivateObject(ByRef obj As CPersistentObject, ByVal conn As _CConnection, ByVal deleteSuperClass As Boolean) + Private Sub deletePrivateObject(ByRef obj As IPersistableObject, ByVal conn As _CConnection, ByVal deleteSuperClass As Boolean) Dim clMap As CClassMap - clMap = obj.getClassMap(obj) + clMap = obj.getClassMap Dim cm As CClassMap cm = clMap @@ -870,9 +877,9 @@ Dim udaMap As CUDAMap Dim aCriteria As CRetrieveCriteria Dim cursor As CCursor - Dim Value As CPersistentObject + Dim Value As IPersistableObject Dim ValueVar As String - Dim col As CPersistentCollection + Dim col As IList Dim colCriteriaParameters As New Collection Dim i As Short, j As Short, k As Short Dim myKeys(cm.AssociationMaps.Count) As String @@ -885,7 +892,8 @@ If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then Value = obj.getObjectByAttribute(udaMap.Target) If Not Value Is Nothing Then - If Value.Retrieve() Then + If retrieveObject(Value, False, True) Then + 'If Value.Retrieve() Then deletePrivateObject(Value, conn, deleteSuperClass) End If End If @@ -894,7 +902,8 @@ If Not col Is Nothing Then For k = 0 To col.Count - 1 Value = col.Item(k) - If Value.Retrieve Then + If retrieveObject(Value, False, True) Then + 'If Value.Retrieve Then deletePrivateObject(Value, conn, deleteSuperClass) End If Next k @@ -905,25 +914,6 @@ End If Next i - 'Delete any objects that inherit from this one - 'Dim delCriteria As CDeleteCriteria - 'For Each cm In clMap.ChildrenMaps - ' 'No need to delete if the child data is in the same record as the parent (ie shared tables) - ' If cm.SharedTableField Is Nothing Then - ' delCriteria = New CDeleteCriteria - ' delCriteria.ClassMap = cm - ' For Each am As CAttributeMap In cm.ReferenceAttributeMaps - ' ValueVar = cm.getValueForRelationalDatabase(obj.getValueByAttribute(am.AttributeMap.Name)) - ' aCriteria.WhereCondition.addSelectEqualTo(am.Name, ValueVar) - ' Next am - ' Try - ' delCriteria.perform() - ' Catch ex As Exception - ' End Try - ' delCriteria = Nothing - ' End If - 'Next cm - Dim statement As CSqlStatement statement = clMap.getDeleteSqlFor(obj) conn.processStatement(statement) @@ -933,7 +923,8 @@ If Not cm Is Nothing Then 'delete super class and its associations Value = obj.getObjectByClassMap(cm) - If Value.Retrieve() Then + If retrieveObject(Value, False, True) Then + 'If Value.Retrieve() Then deletePrivateObject(Value, conn, True) End If End If @@ -1247,7 +1238,7 @@ Dim i As Integer Dim t As Type Dim outString As String - Dim obj As CPersistentObject + Dim obj As IPersistableObject Dim ck As CCacheKey outString = ">>>> START CACHE DUMP <<<<" & vbCrLf @@ -1255,7 +1246,7 @@ For Each x In m_cache ce = x.Value obj = ce.PersistentObject - t = obj.GetType + t = obj.GetObjectType ck = x.Key outString &= i.ToString & "> " & t.ToString & " Dirty:" & obj.IsDirty.ToString & _ " Persistent:" & obj.Persistent.ToString & _ @@ -2099,6 +2090,7 @@ 'Dim stack As New Stack Dim queue As New Queue Dim i, k As Integer + Dim tmpObj As Object 'Determine if the object needs saving If Not checkAssociationsRecursivly Then @@ -2123,8 +2115,8 @@ If includeBaseObject AndAlso _ (obj.IsDirty AndAlso Not obj.IsProxy AndAlso Not obj.isReadOnly AndAlso Not obj.isModifyOnly) Then If TypeOf (obj) Is CPersistentObject Then - If Not CType(obj, CPersistentObject).IsValid Then 'Do not save if object is not valid - obj.IsDirty = False 'Added to queue so clear dirty flag + If Not CType(obj, CPersistentObject).IsValid Then 'Do not save if object is not valid + obj.IsDirty = False 'Added to queue so clear dirty flag queue.Enqueue(obj) End If Else @@ -2145,17 +2137,24 @@ udamap = cm.getStraightAssociationMap(i) If udamap.SaveAutomatic Then If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - value = obj.getObjectByAttribute(udamap.Target) - If Not value Is Nothing Then - For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) - queue.Enqueue(o) - Next + tmpObj = obj.GetObjectByAttribute(udamap.Target) + If Not tmpObj Is Nothing Then + If Not value Is Nothing Then + For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) + queue.Enqueue(o) + Next + End If End If ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.getCollectionByAttribute(udamap.Target) + col = obj.GetCollectionByAttribute(udamap.Target) If Not col Is Nothing Then For k = 0 To col.Count() - 1 - value = col.Item(k) + tmpObj = col.Item(k) + If Not tmpObj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + value = LocateOrCreateInjObject(tmpObj) + Else + value = tmpObj + End If For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) queue.Enqueue(o) Next @@ -2169,17 +2168,24 @@ udamap = cm.getInverseAssociationMap(i) If udamap.SaveAutomatic Then If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - value = obj.getObjectByAttribute(udamap.Target) - If Not value Is Nothing Then - For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) - queue.Enqueue(o) - Next + tmpObj = obj.GetObjectByAttribute(udamap.Target) + If Not tmpObj Is Nothing Then + If Not value Is Nothing Then + For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) + queue.Enqueue(o) + Next + End If End If ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.getCollectionByAttribute(udamap.Target) + col = obj.GetCollectionByAttribute(udamap.Target) If Not col Is Nothing Then For k = 0 To col.Count() - 1 - value = col.Item(k) + tmpObj = col.Item(k) + If Not tmpObj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + value = LocateOrCreateInjObject(tmpObj) + Else + value = tmpObj + End If For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) queue.Enqueue(o) Next @@ -2195,7 +2201,12 @@ 'is not added to the stack as it will be saved in savePrivateObject() If cm.SharedTableField Is Nothing Then If Not cm.SuperClass Is Nothing Then - value = obj.getObjectByClassMap(cm.SuperClass) + tmpObj = obj.GetObjectByClassMap(cm.SuperClass) + If Not tmpObj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + value = LocateOrCreateInjObject(tmpObj) + Else + value = tmpObj + End If queue.Enqueue(value) value.IsDirty = False 'Added to queue so clear dirty flag For Each o In getObjectsToSave(value, False, checkAssociationsRecursivly) @@ -2204,7 +2215,12 @@ End If Else If Not cm.SuperClass Is Nothing Then - value = obj.getObjectByClassMap(cm.SuperClass) + tmpObj = obj.GetObjectByClassMap(cm.SuperClass) + If Not tmpObj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + value = LocateOrCreateInjObject(tmpObj) + Else + value = tmpObj + End If value.IsDirty = False 'make sure that the parent object is not added For Each o In getObjectsToSave(value, False, checkAssociationsRecursivly) queue.Enqueue(o) @@ -2312,29 +2328,42 @@ m_cache.Clear() End Sub - Public Sub GetObject(ByVal obj As Object) + Public Sub GetObject(ByRef obj As Object) Dim injObj As CInjectedObject - injObj = New CInjectedObject(obj) - If m_injectedObjects.Exists(obj) Then - Return - Else + If injObj Is Nothing Then + injObj = New CInjectedObject(obj) retrieveObject(injObj, False, True) + m_injectedObjects.Add(injObj) + obj = injObj.GetSourceObject + Else + obj = injObj.GetSourceObject End If End Sub - Public Sub FindObject(ByVal obj As Object) + Public Sub FindObject(ByRef obj As Object) Dim injObj As CInjectedObject - injObj = New CInjectedObject(obj) - If m_injectedObjects.Exists(obj) Then - Return - Else + injObj = m_injectedObjects.LocateObject(obj) + If injObj Is Nothing Then + injObj = New CInjectedObject(obj) retrieveObject(injObj, True, True) m_injectedObjects.Add(injObj) + obj = injObj.GetSourceObject + Else + obj = injObj.GetSourceObject End If End Sub Public Function getInjectedObject(ByVal obj As Object) As CInjectedObject - Return m_injectedObjects.Find(obj) + Return m_injectedObjects.LocateObject(obj) + End Function + + Public Function LocateOrCreateInjObject(ByVal obj As Object) As CInjectedObject + Dim injObj As CInjectedObject + injObj = m_injectedObjects.LocateObject(obj) + If injObj Is Nothing Then + injObj = New CInjectedObject(obj) + End If + Return injObj End Function Public Sub StartTracking(ByVal obj As Object) @@ -2343,18 +2372,43 @@ m_injectedObjects.Add(injObj) End Sub - Public Function GetCurrentState(ByVal obj As Object) As CInjectedObject.State + Public Function ObjectIsTracked(ByVal obj) As Boolean + Debug.WriteLine(m_injectedObjects) + Return m_injectedObjects.isTracked(obj) + End Function + + Public Sub MarkForDeletion(ByVal obj As Object) + MarkForDeletion(obj, False) + End Sub + + Public Sub MarkForDeletion(ByVal obj As Object, ByVal deleteParents As Boolean) Dim injObj As CInjectedObject - injObj = m_injectedObjects.Find(obj) - If Not injObj Is Nothing Then - Return injObj.CurrentState + injObj = m_injectedObjects.LocateObject(obj) + If injObj Is Nothing Then + 'Nothing to do Else - Return CInjectedObject.State.NotLoaded + injObj.MarkedForDeletion = True + injObj.WillDeleteParents = deleteParents End If - End Function + End Sub - Public Sub MarkForDeletion(ByVal obj As Object) + Public Sub PersistChanges() + PersistChanges(True) + End Sub + Public Sub PersistChanges(ByVal checkAssociationsRecursively As Boolean) + Me.startTransaction() + Try + Dim injObj As CInjectedObject + For Each de As DictionaryEntry In m_injectedObjects + injObj = de.Value + PersistChanges(injObj.ReferencedObject) + Next + Me.commit() + Catch ex As Exception + Me.rollback() + Throw ex + End Try End Sub Public Sub PersistChanges(ByVal obj As Object) @@ -2364,33 +2418,37 @@ Public Sub PersistChanges(ByVal obj As Object, ByVal checkAssociationsRecursively As Boolean) Dim value As IPersistableObject Dim queue As Queue - Dim injObj As CInjectedObject - injObj = m_injectedObjects.Find(obj) + + injObj = m_injectedObjects.LocateObject(obj) If injObj Is Nothing Then injObj = New CInjectedObject(obj) End If - queue = getObjectsToSave(injObj, True, checkAssociationsRecursively) - - 'All objects to be saved must be saved in a single transaction. - If queue.Count > 0 Then - startTransaction() - Do While queue.Count > 0 - value = queue.Dequeue() - Try - saveObject(value) - Catch ex As Exception - 'After an error remove the cached object so that the next retrieve - ' will refresh the cache with the item from the database - deleteCachedObject(value) - 'Abort the transaction and throw an error - rollback() - Throw New SaveException(ex.Message, ex) - End Try - value.IsDirty = False - Loop - commit() + If injObj.MarkedForDeletion Then + deleteObject(injObj, injObj.WillDeleteParents) + Else + queue = getObjectsToSave(injObj, True, checkAssociationsRecursively) + 'All objects to be saved must be saved in a single transaction. + If queue.Count > 0 Then + startTransaction() + Do While queue.Count > 0 + value = queue.Dequeue() + Try + saveObject(value) + Catch ex As Exception + 'After an error remove the cached object so that the next retrieve + ' will refresh the cache with the item from the database + deleteCachedObject(value) + 'Abort the transaction and throw an error + rollback() + Throw New SaveException(ex.Message, ex) + End Try + value.IsDirty = False + Loop + commit() + End If End If End Sub + End Class \ No newline at end of file Index: IPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/IPersistentObject.vb,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- IPersistentObject.vb 14 Oct 2004 05:25:02 -0000 1.3 +++ IPersistentObject.vb 15 Oct 2004 06:42:56 -0000 1.4 @@ -10,25 +10,26 @@ Property OriginalModifiedDate() As Date Property AssociationsLoaded() As Boolean Property IsLoading() As Boolean - ReadOnly Property isReadOnly() As Boolean - ReadOnly Property isModifyOnly() As Boolean + ReadOnly Property IsReadOnly() As Boolean + ReadOnly Property IsModifyOnly() As Boolean Property OriginalCacheKey() As CCacheKey - Function getClassMap() As CClassMap - Function getFieldLengthByName(ByVal x As String) As Integer - Function getFieldTypeByName(ByVal x As String) As Type + Function GetClassMap() As CClassMap + Function GetFieldLengthByName(ByVal x As String) As Integer + Function GetFieldTypeByName(ByVal x As String) As Type - Function getCollectionByAttribute(ByVal pName As String) As IList - Function getObjectByAttribute(ByVal pName As String) As IPersistableObject - Function getValueByAttribute(ByVal pName As String) As Object - Sub setAttributeValue(ByVal pName As String, ByRef Value As Object) + Function GetCollectionByAttribute(ByVal pName As String) As IList + Function GetObjectByAttribute(ByVal pName As String) As IPersistableObject + Function GetValueByAttribute(ByVal pName As String) As Object + Sub SetAttributeValue(ByVal pName As String, ByRef Value As Object) Function GetObjectType() As Type Function Equals(ByVal obj As IPersistableObject) As Boolean Function Copy() As IPersistableObject Sub ReplaceWith(ByVal obj As IPersistableObject) Sub ResetOriginalDates() - Function getObjectByClassMap(ByVal classMap As CClassMap) As IPersistableObject + Function GetObjectByClassMap(ByVal classMap As CClassMap) As IPersistableObject + Function GetSourceObject() As Object End Interface Index: CInjectedObjects.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObjects.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- CInjectedObjects.vb 14 Oct 2004 05:25:02 -0000 1.1 +++ CInjectedObjects.vb 15 Oct 2004 06:42:56 -0000 1.2 @@ -1,10 +1,95 @@ +'Injected object keys are hashed on the object itself, not the value of the object +'(unlike the persistence brokers cache which works via key values) + Public Class CInjectedObjectKey - Inherits CCacheKey + Private m_hashCode As Integer + Private m_type As Type + Private m_keyvalues As Collection + + Public Sub New(ByVal obj As Object) + m_keyvalues = New Collection + m_hashCode = obj.GetHashCode + Dim injObj As New CInjectedObject(obj) + populateKey(injObj) + End Sub Public Sub New(ByVal obj As CInjectedObject) - MyBase.new() - populateWith(obj) + m_keyvalues = New Collection + If obj.ReferencedObject Is Nothing Then + m_hashCode = 0 + Else + m_hashCode = obj.ReferencedObject.GetHashCode + End If + populateKey(obj) End Sub + + Public Overrides Function GetHashCode() As Integer + Return m_hashCode + End Function + + Protected Sub populateKey(ByVal obj As IPersistableObject) + Dim cm As CClassMap + Dim i As Integer + Dim am As CAttributeMap + Dim x As Object + + m_keyvalues = New Collection + m_type = obj.GetObjectType + cm = obj.getClassMap + For i = 1 To cm.getKeySize + am = cm.getKeyAttributeMap(i) + x = obj.getValueByAttribute(am.Name) + m_keyvalues.Add(x) + Next + End Sub + + Public Overloads Shared Function Equals(ByVal obj1 As Object, ByVal obj2 As Object) As Boolean + Dim flag As Boolean + Dim i As Integer + Dim key1, key2 As CInjectedObjectKey + key1 = obj1 + key2 = obj2 + Return key1.Equals(key2) + End Function + + Public Overloads Overrides Function Equals(ByVal obj1 As Object) As Boolean + Dim flag As Boolean + Dim i As Integer + Dim key As CInjectedObjectKey + key = obj1 + flag = False + For i = 1 To m_keyvalues.Count + If Me.GetHashCode <> key.GetHashCode Then + Return False + End If + Next + Return True + End Function + + Public Overrides Function ToString() As String + Dim s As String + Dim obj As Object + Dim i As Integer + + s = "" + i = 0 + For Each obj In m_keyvalues + If s.Length > 0 Then + s = s & vbCrLf + End If + i += 1 + Try + s = s & vbTab & i.ToString & ") " & obj.GetType.ToString & ": " & obj.ToString + Catch x As Exception + If obj Is Nothing Then + s = s & vbTab & i.ToString & ") --Null Reference--: " & "Nothing" + Else + s = s & vbTab & i.ToString & ") " & obj.GetType.ToString & ": Unprintable Data" + End If + End Try + Next + Return s + End Function End Class @@ -19,42 +104,51 @@ End If injKey = New CInjectedObjectKey(obj) - 'If Not injKey.hasLegitValues Then - ' Exit Sub - 'End If - If injKey.hasLegitValues AndAlso Not (MyBase.Item(injKey) Is Nothing) Then - 'Replace values if possible, otherwise delete and add new + If Not (MyBase.Item(injKey) Is Nothing) Then Debug.WriteLine("Object: " & obj.GetObjectType.ToString & " is already tracked with key(s):" & vbCrLf & injKey.ToString) Else Debug.WriteLine("Started Tracking " & obj.GetObjectType.ToString & " with keys:" & vbCrLf & injKey.ToString) - 'If obj.getClassMap.RelationalDatabase.getConnection(Nothing).Started Then - ' obj.CurrentState = CInjectedObject.State.Loaded - 'End If MyBase.Add(injKey, obj) End If End Sub - Public Overloads Function Exists(ByVal obj As Object) As Boolean + Public Function LocateObject(ByVal obj As Object) As CInjectedObject + Dim injKey As CInjectedObjectKey Dim injObj As CInjectedObject - injObj = New CInjectedObject(obj) - Return Exists(injObj, False) + injKey = New CInjectedObjectKey(obj) + If Not (MyBase.Item(injKey) Is Nothing) Then + injObj = MyBase.Item(injKey) + Return injObj + Else + Return Nothing + End If + End Function + + Public Overloads Function isTracked(ByVal obj As Object) As Boolean + Dim injObj As CInjectedObject + injObj = LocateObject(obj) + If injObj Is Nothing Then + Return False + Else + Return True + End If End Function Public Overloads Function Exists(ByVal obj As CInjectedObject, ByVal useFindAttributes As Boolean) As Boolean - If Find(obj, useFindAttributes) Is Nothing Then + If FindByValue(obj, useFindAttributes) Is Nothing Then Return False Else Return True End If End Function - Public Overloads Function Find(ByVal obj As Object) As CInjectedObject + Public Overloads Function FindByValue(ByVal obj As Object) As CInjectedObject Dim injObj As CInjectedObject injObj = New CInjectedObject(obj) - Return Find(injObj, False) + Return FindByValue(injObj, False) End Function - Public Overloads Function Find(ByVal obj As CInjectedObject, ByVal useFindAttributes As Boolean) As CInjectedObject + Public Overloads Function FindByValue(ByVal obj As CInjectedObject, ByVal useFindAttributes As Boolean) As CInjectedObject Dim injObj As CInjectedObject Dim x As DictionaryEntry Dim attrmap As CAttributeMap @@ -105,22 +199,32 @@ End Function Public Overloads Sub Remove(ByVal obj As Object) - Dim injObj As CInjectedObject If obj Is Nothing Then Exit Sub End If - injObj = New CInjectedObject(obj) - Dim injkey As New CInjectedObjectKey(injObj) - If Not injkey.hasLegitValues Then - Exit Sub - End If - 'If injObj.getClassMap.RelationalDatabase.getConnection(Nothing).Started Then - ' ce = MyBase.Item(ckey) - ' If Not (ce Is Nothing) Then - ' ce.TransactionType = CCacheEntry.CacheTransaction.Deleted - ' End If - 'Else + Dim injkey As New CInjectedObjectKey(obj) MyBase.Remove(injkey) - 'End If End Sub + + Public Overrides Function ToString() As String + Dim x As DictionaryEntry + Dim injObj As CInjectedObject + Dim i As Integer + Dim t As Type + Dim outString As String + Dim obj As IPersistableObject + Dim key As CInjectedObjectKey + + outString = ">>>> START TRACKED OBJECTS DUMP <<<<" & vbCrLf + i = 1 + For Each x In Me + injObj = x.Value + t = injObj.GetObjectType + key = x.Key + outString &= i.ToString & "> " & t.ToString & vbCrLf & injObj.ToString & vbCrLf + i += 1 + Next x + outString &= ">>>> END TRACKED OBJECTS DUMP <<<<" + Return outString + End Function End Class \ No newline at end of file Index: CClassMap.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CClassMap.vb,v retrieving revision 1.32 retrieving revision 1.33 diff -u -d -r1.32 -r1.33 --- CClassMap.vb 14 Oct 2004 05:25:02 -0000 1.32 +++ CClassMap.vb 15 Oct 2004 06:42:56 -0000 1.33 @@ -1971,6 +1971,10 @@ End Property Public Function CreateObjectInstance() As IPersistableObject + Dim obj As Object + Dim ip As IPersistableObject + Dim pbroker As CPersistenceBroker + If AssemblyPath <> String.Empty Then 'For late loading assemblies Dim objHdl As ObjectHandle @@ -1979,7 +1983,7 @@ Else objHdl = Activator.CreateInstanceFrom(AssemblyPath, ClassNameSpace & "." & Name) End If - Return CType(objHdl.Unwrap(), IPersistableObject) + obj = CType(objHdl.Unwrap, Object) Else Dim t As Type Dim asmArray As [Assembly]() = AppDomain.CurrentDomain.GetAssemblies @@ -2000,8 +2004,16 @@ If Not t Is Nothing Then Exit For Next If t Is Nothing Then Return Nothing - Return Activator.CreateInstance(t) + obj = Activator.CreateInstance(t) End If + Try + ip = CType(obj, IPersistableObject) + Catch ex As Exception + pbroker = getPersistenceBrokerInstance() + pbroker.StartTracking(obj) + ip = pbroker.getInjectedObject(obj) + End Try + Return ip End Function End Class \ No newline at end of file Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- CCacheEntry.vb 14 Oct 2004 05:25:02 -0000 1.18 +++ CCacheEntry.vb 15 Oct 2004 06:42:55 -0000 1.19 @@ -153,6 +153,7 @@ Private m_type As Type Private m_keyvalues As Collection Private m_hasLegitValues As Boolean + Protected m_hashCode As Integer '''----------------------------------------------------------------------------- ''' <summary> @@ -169,6 +170,7 @@ Public Sub New() m_keyvalues = New Collection m_hasLegitValues = False + m_hashCode = 0 End Sub Public Sub New(ByVal obj As IPersistableObject) @@ -194,25 +196,7 @@ End If m_keyvalues.Add(x) Next - End Sub - - '''----------------------------------------------------------------------------- - ''' <summary> - ''' Creates a new instance of a CCacheKey object - ''' </summary> - ''' <param name="oid">The Object ID of the CPersistentObject that will be cached.</param> - ''' <remarks>This will create a new cache key based on a ObjectID value. It is slightly - ''' faster than the other constructor as it does not have to determine and explore the objects key - ''' fields.</remarks> - ''' <history> - ''' [rbanks] 27/11/2003 Created - ''' </history> - '''----------------------------------------------------------------------------- - Public Sub New(ByVal oid As COID) - m_type = oid.GetType - m_keyvalues = New Collection - m_keyvalues.Add(oid.OID) - m_hasLegitValues = True + CalculateHashCode(obj) End Sub '''----------------------------------------------------------------------------- @@ -350,29 +334,37 @@ ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function GetHashCode() As Integer + Return m_hashCode + End Function + + Private Sub CalculateHashCode(ByVal cachedObject) Dim i As Long Dim count As Integer Dim obj As Object Dim t As Type - i = m_type.Name.GetHashCode - count = 1 - For Each obj In m_keyvalues - If Not obj Is Nothing Then - If TypeOf obj Is Integer Then - i += CInt(obj).GetHashCode - ElseIf TypeOf obj Is String Then - i += CStr(obj).GetHashCode - ElseIf TypeOf obj Is Double Then - i += CDbl(obj).GetHashCode - Else - t = obj.GetType - i += t.Name.GetHashCode + If m_hasLegitValues Then + i = m_type.Name.GetHashCode + count = 1 + For Each obj In m_keyvalues + If Not obj Is Nothing Then + If TypeOf obj Is Integer Then + i += CInt(obj).GetHashCode + ElseIf TypeOf obj Is String Then + i += CStr(obj).GetHashCode + ElseIf TypeOf obj Is Double Then + i += CDbl(obj).GetHashCode + Else + t = obj.GetType + i += t.Name.GetHashCode + End If + count += 1 End If - count += 1 - End If - Next - Return CInt(i / count) - End Function + Next + m_hashCode = CInt(i / count) + Else + m_hashCode = cachedObject.GetHashCode + End If + End Sub ''' ----------------------------------------------------------------------------- ''' <summary> @@ -465,19 +457,11 @@ Dim ckey As CCacheKey If obj Is Nothing Then - 'Debug.WriteLine("Rejected attempt to add empty object to cache") Exit Sub End If If obj.IsProxy Then - 'Debug.WriteLine("Rejected attempt to add proxy object to cache") Exit Sub End If - 'If obj.ExpiryInterval > 0 Then - ' ce = New CCacheEntry(obj.ExpiryInterval) - 'Else - ' ce = New CCacheEntry(m_expiryInterval) - 'End If - ' ce.PersistentObject = obj.Copy ckey = New CCacheKey(obj) If Not ckey.hasLegitValues Then Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- CInjectedObject.vb 14 Oct 2004 05:25:02 -0000 1.1 +++ CInjectedObject.vb 15 Oct 2004 06:42:56 -0000 1.2 @@ -1,4 +1,5 @@ Imports System.Reflection +Imports System.Runtime.Remoting 'Class to manage objects injected into the persistence broker 'These will be objects that do not inherit from the cperistentobject class, but which @@ -7,18 +8,9 @@ Public Class CInjectedObject Implements IPersistableObject - Public Enum State - Loaded - Modified - Deleted - Added - NotLoaded - End Enum - Private m_object As Object - Private m_objectState As State Private m_originalObject As Object - Private m_associationsLoaded As Object + Private m_associationsLoaded As Boolean Private m_oid As COID Private m_createdDate As Date 'Set when object is created Private m_modifiedDate As Date 'Set when Dirty flag is set on persisted objects @@ -30,13 +22,14 @@ Private m_retrievedCacheKey As CCacheKey Private m_loading As Boolean Private m_proxy As Boolean + Private m_markedForDeletion As Boolean + Private m_deleteParents As Boolean Public Sub New(ByVal obj As Object) MyBase.New() m_object = obj - 'make a snapshot of the object as it currently exists m_originalObject = Activator.CreateInstance(m_object.GetType) - ReplaceValues(m_object, m_originalObject) + 'ReplaceValues(m_object, m_originalObject) End Sub Public Property ReferencedObject() As Object @@ -57,15 +50,6 @@ End Set End Property - Public Property CurrentState() As State - Get - Return m_objectState - End Get - Set(ByVal Value As State) - m_objectState = Value - End Set - End Property - Public Sub ResetToOriginal() ReplaceValues(m_originalObject, m_object) End Sub @@ -149,6 +133,22 @@ End If End Function + Public Function getOriginalValueByAttribute(ByVal pName As String) As Object + Dim dotPos As Integer + dotPos = pName.IndexOf(".") + If dotPos = -1 Then + Return CallByName(m_originalObject, pName, CallType.Get) + Else + Dim o As Object + Dim objName As String + Dim propertyName As String + objName = pName.Substring(0, dotPos) + propertyName = pName.Substring(dotPos + 1) + o = CallByName(m_originalObject, objName, CallType.Get) + Return CallByName(o, propertyName, CallType.Get) + End If + End Function + Public Property AssociationsLoaded() As Boolean Implements IPersistableObject.AssociationsLoaded Get Return m_associationsLoaded @@ -176,6 +176,24 @@ End Set End Property + Public Property MarkedForDeletion() As Boolean + Get + Return m_markedForDeletion + End Get + Set(ByVal Value As Boolean) + m_markedForDeletion = Value + End Set + End Property + + Public Property WillDeleteParents() As Boolean + Get + Return m_deleteParents + End Get + Set(ByVal Value As Boolean) + m_deleteParents = Value + End Set + End Property + Public Function getFieldLengthByName(ByVal x As String) As Integer Implements IPersistableObject.getFieldLengthByName Return getClassMap.getAttributeMapByString(x, True).ColumnMap.StorageSize() End Function @@ -236,7 +254,13 @@ Return ObjectsMatch(m_object, m_originalObject) End Get Set(ByVal Value As Boolean) - 'Do nothing + 'For injected objects this should only be called from the persistence broker and + 'will indicate that an object has finished loading, etc + 'Since we check for value differences to tell if an object is dirty, we need to + 'replace the original object values with the current ones. + If Value = False Then + ReplaceValues(m_object, m_originalObject) + End If End Set End Property @@ -327,9 +351,13 @@ Public Function getObjectByAttribute(ByVal pName As String) As IPersistableObject Implements IPersistableObject.getObjectByAttribute Dim dotPos As Integer + Dim obj As Object + Dim injobj As CInjectedObject + Dim pbroker As CPersistenceBroker + dotPos = pName.IndexOf(".") If dotPos = -1 Then - Return CallByName(m_object, pName, CallType.Get) + obj = CallByName(m_object, pName, CallType.Get) Else Dim o As Object Dim objName As String @@ -337,8 +365,20 @@ objName = pName.Substring(0, dotPos) propertyName = pName.Substring(dotPos + 1) o = CallByName(m_object, objName, CallType.Get) - Return CallByName(o, propertyName, CallType.Get) + obj = CallByName(o, propertyName, CallType.Get) + End If + If obj Is Nothing Then Return Nothing + If obj.GetType.IsSubclassOf(GetType(IPersistableObject)) Then + injobj = obj + Else + pbroker = getPersistenceBrokerInstance() + injobj = pbroker.getInjectedObject(obj) + If injobj Is Nothing Then + pbroker.StartTracking(obj) + injobj = pbroker.getInjectedObject(obj) + End If End If + Return injobj End Function Public Sub setAttributeValue(ByVal pName As String, ByRef Value As Object) Implements IPersistableObject.setAttributeValue @@ -399,10 +439,13 @@ End Function Public Function Copy() As IPersistableObject Implements IPersistableObject.Copy - Dim m_object2 As Object - m_object2 = Activator.CreateInstance(m_object.GetType) - ReplaceValues(m_object, m_object2) - Return New CInjectedObject(m_object2) + 'Dim m_object2 As Object + Dim injobj As CInjectedObject + injobj = Me.MemberwiseClone + 'm_object2 = Activator.CreateInstance(m_object.GetType) + 'ReplaceValues(m_object, m_object2) + 'injobj = New CInjectedObject(m_object2) + Return injobj End Function Friend Sub ResetOriginalDates() Implements IPersistableObject.ResetOriginalDates @@ -429,16 +472,16 @@ udamap = classMap.getStraightAssociationMap(i) 'If udamap.SaveAutomatic Then If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - obj.setAttributeValue(udamap.Target, Me.getObjectByAttribute(udamap.Target)) + obj.SetAttributeValue(udamap.Target, Me.getObjectByAttribute(udamap.Target)) ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - obj.setAttributeValue(udamap.Target, Me.getCollectionByAttribute(udamap.Target)) + obj.SetAttributeValue(udamap.Target, Me.getCollectionByAttribute(udamap.Target)) End If 'End If Next i 'set object's attributes For i = 1 To classMap.AttributeMaps.Count - obj.setAttributeValue(classMap.getAttributeMap(i).Name, Me.getValueByAttribute(classMap.getAttributeMap(i).Name)) + obj.SetAttributeValue(classMap.getAttributeMap(i).Name, Me.getValueByAttribute(classMap.getAttributeMap(i).Name)) Next 'if it has superclass add its attributes @@ -449,23 +492,23 @@ udamap = cm.getStraightAssociationMap(i) 'If udamap.SaveAutomatic Then If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - obj.setAttributeValue(udamap.Target, Me.getObjectByAttribute(udamap.Target)) + obj.SetAttributeValue(udamap.Target, Me.getObjectByAttribute(udamap.Target)) ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - obj.setAttributeValue(udamap.Target, Me.getCollectionByAttribute(udamap.Target)) + obj.SetAttributeValue(udamap.Target, Me.getCollectionByAttribute(udamap.Target)) End If 'End If Next i 'set superclass's attributes For i = 1 To cm.AttributeMaps.Count - obj.setAttributeValue(cm.getAttributeMap(i).Name, Me.getValueByAttribute(cm.getAttributeMap(i).Name)) + obj.SetAttributeValue(cm.getAttributeMap(i).Name, Me.getValueByAttribute(cm.getAttributeMap(i).Name)) Next cm = cm.SuperClass End While 'copy the OriginalModifiedDate and the ModifiedDate from the child to the parent. 'if we don't do this the object won't get saved correctly on subsequent calls. - obj.setAttributeValue("ModifiedDate", Me.getValueByAttribute("ModifiedDate")) + obj.SetAttributeValue("ModifiedDate", Me.getValueByAttribute("ModifiedDate")) obj.OriginalModifiedDate = Me.OriginalModifiedDate obj.IsDirty = Me.IsDirty @@ -480,5 +523,60 @@ m_originalModDate = Value End Set End Property + + Public Overrides Function ToString() As String + Dim s As String + Dim i As Integer + Dim indent As Integer + Dim formatString As String + + Dim cm As CClassMap + Dim am As CAttributeMap + Dim x As Object + Dim y As Object + Dim xstring As String + Dim ystring As String + + If m_object Is Nothing Then + Return "No object" + End If + + s = Me.GetObjectType.ToString & ": " & vbCrLf + indent = s.Length + formatString = Space(s.Length) & "{0,-9}" & vbTab & "{1,-13}" & vbTab & "{2,-14}" & vbCrLf + s &= [String].Format(formatString, "Attribute", "Current Value", "Original Value") + s &= [String].Format(formatString, "---------", "-------------", "--------------") + i = 0 + cm = getClassMap() + For i = 1 To cm.getKeySize + am = cm.getKeyAttributeMap(i) + x = Me.getValueByAttribute(am.Name) + y = Me.getOriginalValueByAttribute(am.Name) + Try + xstring = x.ToString + Catch ex As Exception + If x Is Nothing Then + xstring = "Nothing" + Else + xstring = "Unprintable" + End If + End Try + Try + ystring = y.ToString + Catch ex As Exception + If y Is Nothing Then + ystring = "Nothing" + Else + ystring = "Unprintable" + End If + End Try + s &= [String].Format(formatString, am.Name, xstring, ystring) + Next + Return s + End Function + + Public Function GetSourceObject() As Object Implements IPersistableObject.GetSourceObject + Return m_object + End Function End Class Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.42 retrieving revision 1.43 diff -u -d -r1.42 -r1.43 --- CPersistentObject.vb 14 Oct 2004 05:25:02 -0000 1.42 +++ CPersistentObject.vb 15 Oct 2004 06:42:56 -0000 1.43 @@ -1769,4 +1769,7 @@ Return Me.GetType End Function + Public Function GetSourceObject() As Object Implements IPersistableObject.GetSourceObject + Return Me + End Function End Class |