You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(56) |
Nov
(13) |
Dec
(36) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(7) |
Feb
(55) |
Mar
(33) |
Apr
(71) |
May
(12) |
Jun
|
Jul
(5) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Richard B. <rb...@us...> - 2005-02-28 23:05:59
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16284/InheritedClasses Modified Files: ManyToManyTests_v2.vb Log Message: New unit tests for many-to-many associations for non-inherited objects. Changed a few unit tests to work under new restrictrions for injected (tracked) objects. Index: ManyToManyTests_v2.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/ManyToManyTests_v2.vb,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- ManyToManyTests_v2.vb 11 Feb 2005 02:53:20 -0000 1.3 +++ ManyToManyTests_v2.vb 28 Feb 2005 23:05:49 -0000 1.4 @@ -1,4 +1,4 @@ -Imports AToMSFramework +Imports Atoms.Framework Imports NUnit.Framework Namespace InheritedClasses @@ -87,6 +87,7 @@ Dim B2 As M2MB = New M2MB B2.Description = "B2" A.M2MBCollection.Add(B2) + B2.M2MACollection.Add(A) Dim A2 As M2MA = New M2MA A2.Description = "A2" B2.M2MACollection.Add(A2) |
From: Richard B. <rb...@us...> - 2005-02-17 22:07:07
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12411 Modified Files: Tag: v2_0 CPersistenceBroker.vb Log Message: Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.89.2.4 retrieving revision 1.89.2.5 diff -u -d -r1.89.2.4 -r1.89.2.5 --- CPersistenceBroker.vb 17 Feb 2005 22:00:55 -0000 1.89.2.4 +++ CPersistenceBroker.vb 17 Feb 2005 22:06:58 -0000 1.89.2.5 @@ -3055,7 +3055,7 @@ toColl = Nothing End If End If - If f.FieldType Is GetType(CPersistentCollection) OrElse f.FieldType.IsSubclassOf(GetType(CPersistentCollection)) Then + If Not toColl Is Nothing AndAlso f.FieldType Is GetType(CPersistentCollection) OrElse f.FieldType.IsSubclassOf(GetType(CPersistentCollection)) Then Dim c As CPersistentCollection c = CType(toColl, CPersistentCollection) If Not c.ContainerObject Is Nothing AndAlso c.ContainerObject.Equals(fromObject) Then |
From: Richard B. <rb...@us...> - 2005-02-17 22:01:13
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10814 Modified Files: Tag: v2_0 CCacheEntry.vb CPersistenceBroker.vb CPersistentCollection.vb Log Message: Make sure collections with a containerobject get retargeted when copying the containerobject. Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.89.2.3 retrieving revision 1.89.2.4 diff -u -d -r1.89.2.3 -r1.89.2.4 --- CPersistenceBroker.vb 16 Feb 2005 22:23:38 -0000 1.89.2.3 +++ CPersistenceBroker.vb 17 Feb 2005 22:00:55 -0000 1.89.2.4 @@ -3055,6 +3055,13 @@ toColl = Nothing End If End If + If f.FieldType Is GetType(CPersistentCollection) OrElse f.FieldType.IsSubclassOf(GetType(CPersistentCollection)) Then + Dim c As CPersistentCollection + c = CType(toColl, CPersistentCollection) + If Not c.ContainerObject Is Nothing AndAlso c.ContainerObject.Equals(fromObject) Then + c.ContainerObject = toObject + End If + End If f.SetValue(toObject.GetSourceObject, toColl) End If Next Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.25.2.4 retrieving revision 1.25.2.5 diff -u -d -r1.25.2.4 -r1.25.2.5 --- CCacheEntry.vb 16 Feb 2005 22:23:38 -0000 1.25.2.4 +++ CCacheEntry.vb 17 Feb 2005 22:00:53 -0000 1.25.2.5 @@ -132,62 +132,6 @@ m_object = m_objectCopyAtTransactionStart End Sub - ' 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) - ' 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. - ' If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then - ' Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) - ' coll = IClone.Clone() - ' Else - ' coll = Nothing - ' End If - ' Else - ' If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then - ' '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 - ' Else - ' coll = Nothing - ' End If - ' End If - ' m_collectionCollection.Add(f.Name, coll) ' End If ' Next - 'End Sub - - '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) - ' 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 - Public Sub New(ByVal lifetime As Double) m_expiryTime = DateAdd(DateInterval.Minute, lifetime, Now) End Sub @@ -956,7 +900,6 @@ For Each x In Me ce = x.Value If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then - 'ce.CopyCollections() ce.CopyObject() End If Next Index: CPersistentCollection.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentCollection.vb,v retrieving revision 1.15.2.1 retrieving revision 1.15.2.2 diff -u -d -r1.15.2.1 -r1.15.2.2 --- CPersistentCollection.vb 16 Feb 2005 22:23:39 -0000 1.15.2.1 +++ CPersistentCollection.vb 17 Feb 2005 22:01:03 -0000 1.15.2.2 @@ -43,7 +43,7 @@ ''' [rbanks] 17/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - <Browsable(False), Obsolete("Changes in collection management have made this obsolete. Please use the ListChanged event for equivalent functionality")> _ + <Browsable(False)> _ Public Property ContainerObject() As CPersistentObject Get Return m_container @@ -198,10 +198,10 @@ Private Sub ItemDirtiedHandler(ByVal sender As Object, ByVal e As EventArgs) ' Debug.WriteLine("Collection trapped item dirtied event for " & sender.GetType.Name) RaiseEvent ItemDirtied(Me, e) - 'If Not Me.ContainerObject Is Nothing Then - ' 'Debug.WriteLine("item dirtied - dirtying container") - ' ContainerObject.SetDirtyFlag() - 'End If + If Not Me.ContainerObject Is Nothing Then + 'Debug.WriteLine("item dirtied - dirtying container") + ContainerObject.SetDirtyFlag() + End If End Sub #End Region |
From: Richard B. <rb...@us...> - 2005-02-16 22:23:49
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2407 Modified Files: Tag: v2_0 AssemblyInfo.vb CCacheEntry.vb CInjectedObject.vb CPersistenceBroker.vb CPersistentCollection.vb CPersistentObject.vb readme.html Log Message: Fixed collections and object state being restored after a transaction aborts. Index: AssemblyInfo.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/AssemblyInfo.vb,v retrieving revision 1.14 retrieving revision 1.14.2.1 diff -u -d -r1.14 -r1.14.2.1 --- AssemblyInfo.vb 23 Dec 2004 01:14:44 -0000 1.14 +++ AssemblyInfo.vb 16 Feb 2005 22:23:38 -0000 1.14.2.1 @@ -25,7 +25,7 @@ ' by using the '*' as shown below -<Assembly: AssemblyVersion("2.1.0.0")> +<Assembly: AssemblyVersion("2.0.0.1")> ''' ----------------------------------------------------------------------------- ''' Project : AToMSFramework Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.89.2.2 retrieving revision 1.89.2.3 diff -u -d -r1.89.2.2 -r1.89.2.3 --- CPersistenceBroker.vb 10 Feb 2005 22:42:11 -0000 1.89.2.2 +++ CPersistenceBroker.vb 16 Feb 2005 22:23:38 -0000 1.89.2.3 @@ -201,7 +201,7 @@ If Not x Is Nothing Then Throw x End If - End Try + End Try End SyncLock End Function @@ -307,6 +307,9 @@ tmpObj = m_cache.Item(obj) End If End If + If tmpObj Is Nothing AndAlso m_cache.Status = CCacheCollection.StatusEnum.Deleted Then + Return False + End If If Not tmpObj Is Nothing Then t = tmpObj.GetObjectType If t Is obj.GetObjectType Or t.IsSubclassOf(obj.GetObjectType) Then @@ -751,12 +754,12 @@ End Try End If If found Then - Value.IsDirty = False 'After populating a new object - Value.OriginalCacheKey = New CCacheKey(Value) + Value.IsDirty = False 'After populating a new object + Value.OriginalCacheKey = New CCacheKey(Value) obj.SetAttributeValue(udaMap.Target, Value.GetSourceObject) + End If End If End If - End If ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then For j = 1 To udaMap.getSize ValueVar = cm.getValueForRelationalDatabase(obj.GetValueByAttribute(udaMap.getEntry(j).FromAttrMap.Name)) @@ -776,11 +779,11 @@ If udaMap.LazyLoad Then cursor.loadProxy(anObjPers.GetSourceObject) Else - cursor.loadObject(anObjPers.GetSourceObject) - 'To prevent recursive associations causing problems we need to add the - 'object to the cache here as a preliminary measure - m_cache.Add(anObjPers) - retrieveAssociations(anObjPers, conn, anObjPers.GetClassMap, useCache) + cursor.loadObject(anObjPers.GetSourceObject) + 'To prevent recursive associations causing problems we need to add the + 'object to the cache here as a preliminary measure + m_cache.Add(anObjPers) + retrieveAssociations(anObjPers, conn, anObjPers.GetClassMap, useCache) End If anObjPers.IsDirty = False 'After populating a new object anObjPers.OriginalCacheKey = New CCacheKey(anObjPers) @@ -979,7 +982,7 @@ Try deletePrivateObject(obj, conn, deleteSuperClass) conn.commit() - Catch ex As Exception + Catch ex As Exception x = New DeleteException(ex.Message, ex) conn.rollback() Finally @@ -994,7 +997,7 @@ If Not x Is Nothing Then Throw x End If - End Try + End Try End SyncLock End Sub @@ -1067,26 +1070,26 @@ udaMap = cm.AssociationMaps.Item(myKeys(i)) If udaMap.DeleteAutomatic Then For j = 1 To udaMap.getSize - If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then + If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then Value = obj.GetObjectByAttribute(udaMap.Target) - If Not Value Is Nothing Then - If retrieveObject(Value, False, True) Then - 'If Value.Retrieve() Then - deletePrivateObject(Value, conn, deleteSuperClass) - End If + If Not Value Is Nothing Then + If retrieveObject(Value, False, True) Then + 'If Value.Retrieve() Then + deletePrivateObject(Value, conn, deleteSuperClass) End If + End If ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then col = obj.GetCollectionByAttribute(udaMap.Target) - If Not col Is Nothing Then - For k = 0 To col.Count - 1 - If col.Item(k).GetType.IsSubclassOf(GetType(CPersistentObject)) Then - Value = col.Item(k) - Else - Value = Me.getInjectedObject(col.Item(k)) - End If - If retrieveObject(Value, False, True) Then + If Not col Is Nothing Then + For k = 0 To col.Count - 1 + If col.Item(k).GetType.IsSubclassOf(GetType(CPersistentObject)) Then + Value = col.Item(k) + Else + Value = Me.getInjectedObject(col.Item(k)) + End If + If retrieveObject(Value, False, True) Then 'If Value.Retrieve Then - deletePrivateObject(Value, conn, deleteSuperClass) + deletePrivateObject(Value, conn, deleteSuperClass) End If Next k col = Nothing @@ -1098,11 +1101,11 @@ Dim statement As CSqlStatement statement = clMap.getDeleteSqlFor(obj) - Try - PCSQLHits.Increment() - Catch - End Try - conn.processStatement(statement) + Try + PCSQLHits.Increment() + Catch + End Try + conn.processStatement(statement) If deleteSuperClass Then cm = cm.SuperClass @@ -1112,9 +1115,9 @@ If retrieveObject(Value, False, True) Then 'If Value.Retrieve() Then deletePrivateObject(Value, conn, True) - End If - End If - End If + End If + End If + End If obj.Persistent = False If m_useCache Then @@ -1123,7 +1126,7 @@ PCCacheSize.RawValue = m_cache.Count Catch End Try - End If + End If colCriteriaParameters = Nothing End Sub @@ -1825,9 +1828,9 @@ Return cursor Catch - firstClassMap.RelationalDatabase.freeConnection(conn) - Return Nothing - End Try + firstClassMap.RelationalDatabase.freeConnection(conn) + Return Nothing + End Try End Function @@ -2508,8 +2511,8 @@ Next Next k End If - End If - End If + End If + End If Next i For i = 1 To cm.getInverseAssociationMapSize @@ -2612,19 +2615,19 @@ Return getObjectsToSave(obj, True, checkAssociationsRecursivly) End Function - Friend Sub GetLoginDetails(ByVal sender As _CRelationalDatabase, ByRef User As String, ByRef Password As String) + Public Sub GetLoginDetails(ByVal sender As _CRelationalDatabase, ByRef User As String, ByRef Password As String) RaiseEvent LoginDetailsNeeded(sender, User, Password) End Sub - Friend Sub startCacheTransaction(ByVal reldb As _CRelationalDatabase) + Public Sub startCacheTransaction(ByVal reldb As _CRelationalDatabase) m_cache.StartTransaction(reldb) End Sub - Friend Sub commitCache(ByVal reldb As _CRelationalDatabase) + Public Sub commitCache(ByVal reldb As _CRelationalDatabase) m_cache.CommitChanges(reldb) End Sub - Friend Sub rollbackCache(ByVal reldb As _CRelationalDatabase) + Public Sub rollbackCache(ByVal reldb As _CRelationalDatabase) m_cache.AbortChanges(reldb) End Sub @@ -2967,13 +2970,13 @@ PCAverageTimeBase.RawValue = 0 Catch ex As Exception Trace.WriteLine("Could not create performance counters. If using ASP.NET please see http://objectsharp.com/Blogs/bruce/archive/2003/12/05/222.aspx" & _ - vbCrLf & ex.Message) + vbCrLf & ex.Message) End Try End Sub Public Shared Sub CopyCollections(ByVal fromObject As IPersistableObject, ByRef toObject As IPersistableObject) Dim t, iEnumerableType, iListType, iDicType As Type - Dim coll, collItem As Object + Dim fromColl, toColl, collItem As Object Dim il As IList Dim id As IDictionary Dim f, fields() As FieldInfo @@ -2990,31 +2993,69 @@ 'Getting the ICloneable interface from the object. If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then Dim IClone As ICloneable = CType(f.GetValue(fromObject.GetSourceObject), ICloneable) - coll = IClone.Clone() + toColl = IClone.Clone() Else - coll = Nothing + toColl = Nothing End If Else - If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + fromColl = f.GetValue(fromObject.GetSourceObject) + If Not fromColl Is Nothing Then 'If the field doesn't support the ICloneable interface then just set it. - coll = Activator.CreateInstance(f.FieldType) + t = f.FieldType + toColl = Activator.CreateInstance(t) 'need to copy references one-by-one + 'Also neeed to connect event handlers of new collection to new object based + 'on event connections of the old collection and the old object + Dim fColl, fieldsColl() As FieldInfo + Dim d, newD, delArray(), newDelArray() As [Delegate] + Dim collDel As MulticastDelegate + While Not t Is Nothing + fieldsColl = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + For Each fColl In fieldsColl + If fColl.FieldType.Name = fColl.Name & "Handler" OrElse fColl.FieldType Is GetType(EventHandler) Then + 'This is an event! + d = fColl.GetValue(fromColl) + collDel = Nothing + If Not d Is Nothing Then + delArray = d.GetInvocationList + For Each d In delArray + If Not d.Target.GetType.GetInterface("IPersistableObject") Is Nothing Then + If CType(d.Target, IPersistableObject).Equals(fromObject.GetSourceObject) Then + newD = MulticastDelegate.CreateDelegate(fColl.FieldType, toObject, d.Method.Name) + If collDel Is Nothing Then + collDel = newD + Else + collDel.Combine(collDel, newD) + End If + End If + End If + Next + fColl.SetValue(toColl, collDel) + End If + End If + Next + If t.IsSubclassOf(GetType(CPersistentCollection)) Then + t = t.BaseType + Else + t = Nothing + End If + End While If Not iListType Is Nothing Then - il = CType(coll, IList) - For Each collItem In f.GetValue(fromObject.GetSourceObject) + il = CType(toColl, IList) + For Each collItem In fromColl il.Add(collItem) Next Else - id = CType(coll, IDictionary) - For Each de As DictionaryEntry In f.GetValue(fromObject.GetSourceObject) + id = CType(toColl, IDictionary) + For Each de As DictionaryEntry In fromColl id.Add(de.Key, de.Value) Next End If Else - coll = Nothing + toColl = Nothing End If End If - f.SetValue(toObject, coll) + f.SetValue(toObject.GetSourceObject, toColl) End If Next End Sub Index: readme.html =================================================================== RCS file: /cvsroot/jcframework/dotnet/readme.html,v retrieving revision 1.7 retrieving revision 1.7.2.1 diff -u -d -r1.7 -r1.7.2.1 --- readme.html 2 Feb 2005 05:08:38 -0000 1.7 +++ readme.html 16 Feb 2005 22:23:39 -0000 1.7.2.1 @@ -117,7 +117,7 @@ <!-- BEGIN faq_block --> <table class="forumline" width="100%" cellspacing="1" cellpadding="2" border="0" align="center"> <tr> - <td class="catHead" height="28" align="center"><span class="cattitle">Atoms Framework 2.1<br />Released: xx-xxx-200x</span></td> + <td class="catHead" height="28" align="center"><span class="cattitle">Atoms Framework 2.0.1<br />Released: 17-Feb-2005</span></td> </tr> <tr> <td align="center"> @@ -149,10 +149,10 @@ </div> <tr> <td class="groupHeader" align="left" valign="top"> - <div onclick="return CFAQ.display('faq_a_notesv2.1', false);" style="width:100%;cursor:pointer;cursor:hand;"> - <span class="gen"><a class="postlink" href="javascript:void(0)" onclick="return CFAQ.display('faq_a_notesv2.1', true);" onfocus="this.blur();"><b>Changes in v2.1 (xx-xxx-xx)</b></a></span> + <div onclick="return CFAQ.display('faq_a_notesv2.0.1', false);" style="width:100%;cursor:pointer;cursor:hand;"> + <span class="gen"><a class="postlink" href="javascript:void(0)" onclick="return CFAQ.display('faq_a_notesv2.0.1', true);" onfocus="this.blur();"><b>Changes in v2.0.1 (17-Feb-05)</b></a></span> </div> - <div id="faq_a_notesv2.1" style="display:none;"> + <div id="faq_a_notesv2.0.1" style="display:none;"> <table class="details" width="100%" cellspacing="0" cellpadding="3" border="0" align="left"> <tr class="tableCaption"><td colspan=3>Bugs:</td></tr> <tr class="tableHeader" valign="bottom"><td valign="top" class="colHeader">Job Id</td> @@ -181,8 +181,8 @@ </tr> <tr valign="top"> <td>1113504</td> - <td class="col1">Collections not restored after transaction rollback</td> - <td>Collections are now cloned or copied at the start of a transaction. If the transaction aborts the copied collections are restored to the object.<td> + <td class="col1">Objects/Collections not restored after transaction rollback</td> + <td>Collections are now cloned or copied at the start of a transaction. If the transaction aborts the copied collections are restored to the object. This also includes objects that were modified but not saved during the transaction<td> </tr> <tr class="tableCaption" valign="bottom"> <td colspan=3><br/>Modifications</td> Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.25.2.3 retrieving revision 1.25.2.4 diff -u -d -r1.25.2.3 -r1.25.2.4 --- CCacheEntry.vb 10 Feb 2005 22:42:11 -0000 1.25.2.3 +++ CCacheEntry.vb 16 Feb 2005 22:23:38 -0000 1.25.2.4 @@ -30,6 +30,7 @@ Private m_object As IPersistableObject Private m_objectCopy As IPersistableObject + Private m_objectCopyAtTransactionStart As IPersistableObject Private m_transactionType As CCacheEntry.CacheTransaction Private m_expiryTime As Date Private m_originalObject As IPersistableObject @@ -115,84 +116,77 @@ End Property Public Sub CopyObject() + 'Need two object copies + 'One for the copy made at the very start of the transaction + 'One for any updates made to the object (via save) during the transaction so that + ' cache reads get the correct copy m_objectCopy = m_object.Copy + m_objectCopyAtTransactionStart = m_object.Copy End Sub - Public Sub RestoreObject() - m_object = m_objectCopy - End Sub - - 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 + Public Sub UpdateObject() + m_objectCopy = m_object.Copy + End Sub - 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) - 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. - If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then - Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) - coll = IClone.Clone() - Else - coll = Nothing - End If - Else - If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then - '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 - Else - coll = Nothing - End If - End If - m_collectionCollection.Add(f.Name, coll) - End If - Next + Public Sub RestoreObject() + m_object = m_objectCopyAtTransactionStart End Sub - Public Sub RestoreCollections() - Dim t, iEnumerableType, iListType, iDicType As Type - Dim f, fields() As FieldInfo + ' 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 - 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) - 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 + ' '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) + ' 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. + ' If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then + ' Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) + ' coll = IClone.Clone() + ' Else + ' coll = Nothing + ' End If + ' Else + ' If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then + ' '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 + ' Else + ' coll = Nothing + ' End If + ' End If + ' m_collectionCollection.Add(f.Name, coll) ' End If ' Next + 'End Sub + + '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) + ' 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 Public Sub New(ByVal lifetime As Double) m_expiryTime = DateAdd(DateInterval.Minute, lifetime, Now) @@ -587,6 +581,13 @@ Private m_expiryInterval As Double Private m_objectsLoading As Boolean + Public Enum StatusEnum + Found + NotFound + Deleted + End Enum + Private m_status As StatusEnum + '''----------------------------------------------------------------------------- ''' <summary> ''' Adds a persistent object to the cache. @@ -630,7 +631,6 @@ End If If obj.GetClassMap.RelationalDatabase.getConnection(Nothing).Started Then ce.TransactionType = CCacheEntry.CacheTransaction.Saved - ce.CopyObject() End If Try ce.OriginalObject = obj @@ -713,15 +713,18 @@ If found Then 'Debug.WriteLine("Cache - Found object in cache") If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted Then + m_status = StatusEnum.Deleted Return Nothing End If Debug.WriteLine([String].Format("Cache - getting {0} object from cache. Key..." & vbCrLf & x.Key.ToString, x.Key.ObjType.Name)) + m_status = StatusEnum.Found Return GetCachedObject(ce) End If End If End If End While 'Debug.WriteLine("Cache - object not cached") + m_status = StatusEnum.NotFound Return Nothing End Function @@ -743,16 +746,22 @@ Get Dim ce As CCacheEntry ce = MyBase.Item(OIDValue) - If ce Is Nothing Then Return Nothing + If ce Is Nothing Then + m_status = StatusEnum.NotFound + Return Nothing + End If If ce.IsExpired() And Not ce.PersistentObject.IsDirty Then 'Debug.WriteLine("Cache - removing expired object: " & OIDValue) - MyBase.Remove(Item) 'delete object from cache + MyBase.Remove(Item) 'delete object from cache + m_status = StatusEnum.NotFound Return Nothing End If 'Debug.WriteLine("Cache - returning copy of object from cache" & OIDValue) If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted Then + m_status = StatusEnum.Deleted Return Nothing End If + m_status = StatusEnum.Found Return GetCachedObject(ce) End Get End Property @@ -778,19 +787,26 @@ Dim ckey As CCacheKey ckey = New CCacheKey(obj) If Not ckey.hasLegitValues Then + m_status = StatusEnum.NotFound Return Nothing End If ce = MyBase.Item(ckey) - If ce Is Nothing Then Return Nothing + If ce Is Nothing Then + m_status = StatusEnum.NotFound + Return Nothing + End If If ce.IsExpired() And Not ce.PersistentObject.IsDirty Then 'Debug.WriteLine([String].Format("Cache - removing expired {0} object. Key... " & vbCrLf & ckey.ToString, ckey.ObjType.Name)) - MyBase.Remove(ckey) 'delete object from cache + MyBase.Remove(ckey) 'delete object from cache + m_status = StatusEnum.NotFound Return Nothing End If If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted Then + m_status = StatusEnum.Deleted Return Nothing End If Debug.WriteLine([String].Format("Cache - getting {0} object from cache. Key..." & vbCrLf & ckey.ToString, ckey.ObjType.Name)) + m_status = StatusEnum.Found Return GetCachedObject(ce) End Get End Property @@ -900,16 +916,23 @@ 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 + If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then + Select Case ce.TransactionType + Case CCacheEntry.CacheTransaction.None + 'Even though an object hasn't been saved/deleted it may still have been + 'modified so we must restore it in any case + ce.RestoreObject() + Case CCacheEntry.CacheTransaction.Deleted + 'Lets cancel deletes first - just means resetting transaction to None + ce.TransactionType = CCacheEntry.CacheTransaction.None + 'ce.RestoreCollections() + ce.RestoreObject() + Case CCacheEntry.CacheTransaction.Saved + 'Now look for cache entries to be saved and restore them + ce.RestoreObject() + 'ce.RestoreCollections() + ce.TransactionType = CCacheEntry.CacheTransaction.None + End Select End If Next @@ -933,7 +956,8 @@ For Each x In Me ce = x.Value If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then - ce.CopyCollections() + 'ce.CopyCollections() + ce.CopyObject() End If Next End Sub @@ -1004,4 +1028,10 @@ Return outString End Function + + Public ReadOnly Property Status() As StatusEnum + Get + Return m_status + End Get + End Property End Class \ No newline at end of file Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.9.2.2 retrieving revision 1.9.2.3 diff -u -d -r1.9.2.2 -r1.9.2.3 --- CInjectedObject.vb 10 Feb 2005 22:42:11 -0000 1.9.2.2 +++ CInjectedObject.vb 16 Feb 2005 22:23:38 -0000 1.9.2.3 @@ -76,15 +76,20 @@ End If Dim f, fields() As FieldInfo Dim value As Object - Dim t As Type + Dim t, iListType, iDicType As Type Try t = sourceObject.GetType While Not t Is Nothing fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) 'Note that this will copy event handlers as well For Each f In fields - value = f.GetValue(sourceObject) - f.SetValue(targetObject, value) + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + 'Do not copy collections yet - we'll do that at the end + If iListType Is Nothing AndAlso iDicType Is Nothing Then + value = f.GetValue(sourceObject) + f.SetValue(targetObject, value) + End If Next If Not t.BaseType Is Nothing Then t = t.BaseType @@ -92,6 +97,7 @@ t = Nothing End If End While + CPersistenceBroker.CopyCollections(sourceObject, targetObject) Catch ex As Exception Debug.WriteLine(ex.Message) End Try Index: CPersistentCollection.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentCollection.vb,v retrieving revision 1.15 retrieving revision 1.15.2.1 diff -u -d -r1.15 -r1.15.2.1 --- CPersistentCollection.vb 21 Dec 2004 21:57:12 -0000 1.15 +++ CPersistentCollection.vb 16 Feb 2005 22:23:39 -0000 1.15.2.1 @@ -1,5 +1,7 @@ Option Explicit On Imports System.ComponentModel +Imports System.Reflection + '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CPersistentCollection @@ -41,7 +43,8 @@ ''' [rbanks] 17/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - <Browsable(False)> Public Property ContainerObject() As CPersistentObject + <Browsable(False), Obsolete("Changes in collection management have made this obsolete. Please use the ListChanged event for equivalent functionality")> _ + Public Property ContainerObject() As CPersistentObject Get Return m_container End Get @@ -195,10 +198,10 @@ Private Sub ItemDirtiedHandler(ByVal sender As Object, ByVal e As EventArgs) ' Debug.WriteLine("Collection trapped item dirtied event for " & sender.GetType.Name) RaiseEvent ItemDirtied(Me, e) - If Not Me.ContainerObject Is Nothing Then - 'Debug.WriteLine("item dirtied - dirtying container") - ContainerObject.SetDirtyFlag() - End If + 'If Not Me.ContainerObject Is Nothing Then + ' 'Debug.WriteLine("item dirtied - dirtying container") + ' ContainerObject.SetDirtyFlag() + 'End If End Sub #End Region @@ -342,4 +345,49 @@ RaiseEvent Disposed(Me, EventArgs.Empty) End Sub #End Region + + '#Region "ICloneable Interface" + ' Public Function Clone() As Object Implements System.ICloneable.Clone + ' Dim obj As CPersistentCollection + ' 'obj = Me.MemberwiseClone + ' 'Use reflection to copy all of the fields from Obj to me (by value) + ' Dim f, fields() As FieldInfo + ' Dim e, events() As EventInfo + ' Dim value As Object + ' Dim t As Type + ' Dim d, newD, delArray() As [Delegate] + ' Try + ' t = Me.GetType + ' obj = Activator.CreateInstance(t) + ' While Not t Is Nothing + ' fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + ' 'Note that this will copy event handlers as well + ' For Each f In fields + ' If f.FieldType.Name = f.Name & "Handler" Then + ' 'This is an event! + ' d = f.GetValue(Me) + ' If Not d Is Nothing Then + ' delArray = d.GetInvocationList + ' For Each d In delArray + ' If d.Target.Equals(obj) Then + ' newD = [Delegate].CreateDelegate(f.FieldType, obj, d.Target) + ' End If + ' Next + ' End If + ' End If + ' value = f.GetValue(Me) + ' f.SetValue(obj, value) + ' Next + ' If t.IsSubclassOf(GetType(CPersistentCollection)) Then + ' t = t.BaseType + ' Else + ' t = Nothing + ' End If + ' End While + ' Catch ex As Exception + ' Debug.WriteLine(ex.Message) + ' End Try + ' Return obj + ' End Function + '#End Region End Class Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.52.2.1 retrieving revision 1.52.2.2 diff -u -d -r1.52.2.1 -r1.52.2.2 --- CPersistentObject.vb 10 Feb 2005 22:42:13 -0000 1.52.2.1 +++ CPersistentObject.vb 16 Feb 2005 22:23:39 -0000 1.52.2.2 @@ -675,7 +675,7 @@ Return CallByName(o, propertyName, CallType.Get) End If Catch err As Exception - Throw New Exception("getCollectionByAttribute failed", err) + Throw New Exception("getCollectionByAttribute failed for class " & me.getclassmap.name & " attribute: " & " " & pname, err) End Try End Function @@ -901,16 +901,16 @@ Do While queue.Count > 0 value = queue.Dequeue() Try - ckey = New CCacheKey(value) - If savedKeys.Contains(ckey) Then - 'object was already saved (could be new object referenced by multiple other new objects) - Debug.WriteLine("The object with key " & ckey.ToString & " was already saved once") - Else - persistentBroker.saveObject(value) - 'Need to recalculate the key here to handle objects using identity (autonumber) keys ckey = New CCacheKey(value) - savedKeys.Add(ckey) - End If + If savedKeys.Contains(ckey) Then + 'object was already saved (could be new object referenced by multiple other new objects) + Debug.WriteLine("The object with key " & ckey.ToString & " was already saved once") + Else + persistentBroker.saveObject(value) + 'Need to recalculate the key here to handle objects using identity (autonumber) keys + ckey = New CCacheKey(value) + savedKeys.Add(ckey) + End If 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 @@ -1112,12 +1112,18 @@ ''' </history> '''----------------------------------------------------------------------------- Public Sub SetDirtyFlag() + Static eventRaised As Boolean If m_persistent = True Then m_modifiedDate = Now 'Only set modified if the object is already persistent 'Set milliseconds to zero to avoid issues with millisecond inconsistencies in SQL db's m_modifiedDate = m_modifiedDate.AddMilliseconds(-m_modifiedDate.Millisecond) If m_dirty = False Then - RaiseEvent MarkedAsDirty(Me, New EventArgs) + If Not eventRaised Then + 'Was getting stack overflow with direct many-to-many associations due to circular event raising + eventRaised = True + RaiseEvent MarkedAsDirty(Me, New EventArgs) + eventRaised = False + End If End If End If m_dirty = True @@ -1225,10 +1231,14 @@ '''----------------------------------------------------------------------------- Public Overridable Function Copy() As IPersistableObject Implements IPersistentObject.Copy Dim obj As CPersistentObject - obj = CType(Me.MemberwiseClone, CPersistentObject) + obj = Me.getClassMap.CreateObjectInstance + obj.ReplaceWith(Me) + 'obj = CType(Me.MemberwiseClone, CPersistentObject) 'Because memberwise clone only reference copies collections we should also 'copy the collections as well, since failing to do so can corrupt the cache. - CPersistenceBroker.CopyCollections(Me, obj) + 'This will also connect events from the collections to the new object based on + 'existing event handlers in "Me" + 'CPersistenceBroker.CopyCollections(Me, obj) Return obj End Function @@ -1246,22 +1256,27 @@ '''----------------------------------------------------------------------------- Public Overridable Sub ReplaceWith(ByVal obj As IPersistableObject) Implements IPersistentObject.ReplaceWith 'Use reflection to copy all of the fields from Obj to me (by value) + 'Also copy collections If obj Is Nothing Then Return If Not obj.GetObjectType Is Me.GetObjectType Then Throw New Exception("Objects must be of the same type") End If Dim f, fields() As FieldInfo Dim value As Object - Dim t As Type + Dim t, iListType, iDicType As Type Try t = Me.GetType While Not t Is Nothing fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) 'Note that this will copy event handlers as well For Each f In fields - ' Debug.WriteLine(f.Name) - value = f.GetValue(obj) - f.SetValue(Me, value) + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + 'Do not copy collections yet - we'll do that at the end + If iListType Is Nothing AndAlso iDicType Is Nothing Then + value = f.GetValue(obj) + f.SetValue(Me, value) + End If Next If t.IsSubclassOf(GetType(CPersistentObject)) Then t = t.BaseType @@ -1269,6 +1284,7 @@ t = Nothing End If End While + CPersistenceBroker.CopyCollections(obj, Me) Catch ex As Exception Debug.WriteLine(ex.Message) End Try @@ -1663,37 +1679,37 @@ Return obj End Function - <EditorBrowsable(EditorBrowsableState.Advanced)> _ - Public Overridable Function GetBaseCopy() As CPersistentObject - 'Use reflection to copy all of the fields from Obj to me (by value) - If Me.getClassMap.SuperClass Is Nothing Then - Return Nothing - End If - Dim obj As CPersistentObject = Me.getClassMap.SuperClass.CreateObjectInstance - Dim f, fields() As FieldInfo - Dim value As Object - Dim t As Type - Try - t = obj.GetType - While Not t Is Nothing - fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) - 'Note that this will copy event handlers as well - For Each f In fields - value = f.GetValue(Me) - f.SetValue(obj, value) - Next - If t.IsSubclassOf(GetType(CPersistentObject)) Then - t = t.BaseType - Else - t = Nothing - End If - End While - Return obj - Catch ex As Exception - Debug.WriteLine(ex.Message) - End Try - Return Nothing - End Function + '<EditorBrowsable(EditorBrowsableState.Advanced)> _ + 'Public Overridable Function GetBaseCopy() As CPersistentObject + ' 'Use reflection to copy all of the fields from Obj to me (by value) + ' If Me.getClassMap.SuperClass Is Nothing Then + ' Return Nothing + ' End If + ' Dim obj As CPersistentObject = Me.getClassMap.SuperClass.CreateObjectInstance + ' Dim f, fields() As FieldInfo + ' Dim value As Object + ' Dim t As Type + ' Try + ' t = obj.GetType + ' While Not t Is Nothing + ' fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + ' 'Note that this will copy event handlers as well + ' For Each f In fields + ' value = f.GetValue(Me) + ' f.SetValue(obj, value) + ' Next + ' If t.IsSubclassOf(GetType(CPersistentObject)) Then + ' t = t.BaseType + ' Else + ' t = Nothing + ' End If + ' End While + ' Return obj + ' Catch ex As Exception + ' Debug.WriteLine(ex.Message) + ' End Try + ' Return Nothing + 'End Function #End Region |
From: Richard B. <rb...@us...> - 2005-02-16 22:22:44
|
Update of /cvsroot/jcframework/Nunit In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2012 Modified Files: Tag: v2_0 AtomsFramework.xml original db1.mdb Log Message: Fixed XML and database schema for tests Index: original db1.mdb =================================================================== RCS file: /cvsroot/jcframework/Nunit/original db1.mdb,v retrieving revision 1.12 retrieving revision 1.12.2.1 diff -u -d -r1.12 -r1.12.2.1 Binary files /tmp/cvsWZ5rhq and /tmp/cvsIbCzfW differ Index: AtomsFramework.xml =================================================================== RCS file: /cvsroot/jcframework/Nunit/AtomsFramework.xml,v retrieving revision 1.15 retrieving revision 1.15.2.1 diff -u -d -r1.15 -r1.15.2.1 --- AtomsFramework.xml 2 Jan 2005 09:41:09 -0000 1.15 +++ AtomsFramework.xml 16 Feb 2005 22:22:29 -0000 1.15.2.1 @@ -118,14 +118,13 @@ <attribute name="Id" column="id" key="primary"/> <attribute name="field1" column="field1" /> <attribute name="AId" column="a_id" /> - <attribute name="TableA" /> - <attribute name="TableDCollection" /> + <attrbute name="TableA" /> </class> <class name="TableC" table="TableC" database="MSA" namespace="NunitTests.InheritedClasses"> <attribute name="Id" column="id" key="primary"/> <attribute name="field1" column="field1" /> <attribute name="AId" column="a_id" /> - <attribute name="TableA" /> + <attrbute name="TableA" /> </class> <association fromClass="NunitTests.InheritedClasses.TableA" toClass="NunitTests.InheritedClasses.TableB" target="TableBCollection" cardinality="OneToMany" retrieveAutomatic="true" saveAutomatic="true" deleteAutomatic="true" inverse="false" name="AtoB"> @@ -306,7 +305,22 @@ inverse="false"> <entry fromAttribute="BOID" toAttribute="OIDValue"/> </association> - + + <class name="LazyEmployee" table="NPEmployee" database="MSA" namespace="NunitTests.StandardClasses"> + <attribute name="Name" column="name" find="true" key="primary"/> + <attribute name="ReportsToName" column="parentname" /> + <attribute name="ReportsTo" /> + <attribute name="Workers" /> + </class> + <association fromClass="NunitTests.StandardClasses.LazyEmployee" toClass="NunitTests.StandardClasses.LazyEmployee" target="ReportsTo" cardinality="OneToOne" + retrieveAutomatic="lazy" saveAutomatic="true" deleteAutomatic="false" inverse="false"> + <entry fromAttribute="ReportsToName" toAttribute="Name"/> + </association> + <association fromClass="NunitTests.StandardClasses.LazyEmployee" toClass="NunitTests.StandardClasses.LazyEmployee" target="Workers" cardinality="OneToMany" + retrieveAutomatic="lazy" saveAutomatic="true" deleteAutomatic="false" inverse="false"> + <entry fromAttribute="Name" toAttribute="ReportsToName"/> + </association> + <class name="ManyToManyA" table="ManyToManyA" database="MSA" namespace="NunitTests.InheritedClasses"> <attribute name="GUIDValue" column="GuidValue" key="primary"/> <attribute name="Description" column="description" /> @@ -348,19 +362,5 @@ <entry fromAttribute="BGuidValue" toAttribute="GUIDValue"/> </association> - <class name="LazyEmployee" table="NPEmployee" database="MSA" namespace="NunitTests.StandardClasses"> - <attribute name="Name" column="name" find="true" key="primary"/> - <attribute name="ReportsToName" column="parentname" /> - <attribute name="ReportsTo" /> - <attribute name="Workers" /> - </class> - <association fromClass="NunitTests.StandardClasses.LazyEmployee" toClass="NunitTests.StandardClasses.LazyEmployee" target="ReportsTo" cardinality="OneToOne" - retrieveAutomatic="lazy" saveAutomatic="true" deleteAutomatic="false" inverse="false"> - <entry fromAttribute="ReportsToName" toAttribute="Name"/> - </association> - <association fromClass="NunitTests.StandardClasses.LazyEmployee" toClass="NunitTests.StandardClasses.LazyEmployee" target="Workers" cardinality="OneToMany" - retrieveAutomatic="lazy" saveAutomatic="true" deleteAutomatic="false" inverse="false"> - <entry fromAttribute="Name" toAttribute="ReportsToName"/> - </association> </map> \ No newline at end of file |
From: Richard B. <rb...@us...> - 2005-02-14 02:24:27
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24223/InheritedClasses Modified Files: ManyToManyClasses_v2.vb TableA_B.vb tblAtoKClasses.vb Removed Files: ManyToManyClasses.vb ManyToManyTests.vb Log Message: Update unit tests for many-to-many and remove old unit tests for previous method of doing N:M associations. Index: tblAtoKClasses.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/tblAtoKClasses.vb,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- tblAtoKClasses.vb 2 Jan 2005 09:41:10 -0000 1.5 +++ tblAtoKClasses.vb 14 Feb 2005 02:24:12 -0000 1.6 @@ -9,11 +9,10 @@ Public _c As C Public _cOID As String - Public _bCol As CPersistentCollection + Public WithEvents _bCol As CPersistentCollection Public Sub New() _bCol = New CPersistentCollection - _bCol.ContainerObject = Me Me.SetDirtyFlag() End Sub @@ -106,6 +105,10 @@ Public Overrides Function IsValid() As Boolean Return True End Function + + Private Sub _bCol_ListChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles _bCol.ListChanged + Me.SetDirtyFlag() + End Sub End Class Public Class B @@ -113,7 +116,6 @@ Public Sub New() _nCol = New CPersistentCollection - _nCol.ContainerObject = Me Me.SetDirtyFlag() End Sub @@ -121,7 +123,7 @@ Public _text As String = String.Empty Public _a As A = Nothing Public _aOID As String = Nothing - Public _nCol As CPersistentCollection + Public WithEvents _nCol As CPersistentCollection Public Property Id() As Integer Get @@ -211,6 +213,10 @@ Public Overloads Overrides Function IsValid() As Boolean Return True End Function + + Private Sub _nCol_ListChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles _nCol.ListChanged + Me.SetDirtyFlag() + End Sub End Class Public Class C @@ -226,8 +232,8 @@ Return Me._id End Get Set(ByVal Value As Integer) - If Not (Me._id = value) Then - Me._id = value + If Not (Me._id = Value) Then + Me._id = Value Me.SetDirtyFlag() End If End Set @@ -238,8 +244,8 @@ Return Me._text End Get Set(ByVal Value As String) - If Not (Me._text = value) Then - Me._text = value + If Not (Me._text = Value) Then + Me._text = Value Me.SetDirtyFlag() End If End Set --- ManyToManyClasses.vb DELETED --- Index: TableA_B.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/TableA_B.vb,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- TableA_B.vb 6 Feb 2005 02:45:19 -0000 1.5 +++ TableA_B.vb 14 Feb 2005 02:24:12 -0000 1.6 @@ -58,19 +58,14 @@ Me.SetDirtyFlag() End Sub - Public Sub New() - _tableBCol.ContainerObject = Me - _tableCCol.ContainerObject = Me - End Sub - - Private Sub _tableBCol_ObjectAdded(ByVal index As Integer, ByRef value As Object) Handles _tableBCol.ObjectAdded - Me.SetDirtyFlag() - End Sub + Private Sub _tableBCol_ObjectAdded(ByVal index As Integer, ByRef value As Object) Handles _tableBCol.ObjectAdded + Me.SetDirtyFlag() + End Sub - Private Sub _tableBCol_ObjectRemoved(ByVal index As Integer, ByRef value As Object) Handles _tableBCol.ObjectRemoved - Me.SetDirtyFlag() - End Sub - End Class + Private Sub _tableBCol_ObjectRemoved(ByVal index As Integer, ByRef value As Object) Handles _tableBCol.ObjectRemoved + Me.SetDirtyFlag() + End Sub + End Class Public Class TableB Inherits CPersistentObject --- ManyToManyTests.vb DELETED --- Index: ManyToManyClasses_v2.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/ManyToManyClasses_v2.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ManyToManyClasses_v2.vb 9 Feb 2005 06:20:50 -0000 1.1 +++ ManyToManyClasses_v2.vb 14 Feb 2005 02:24:12 -0000 1.2 @@ -6,7 +6,7 @@ Inherits CPersistentObject Private _description As String - Private _bCol As M2MBCollection + Private WithEvents _bCol As M2MBCollection Public Property Description() As String Get @@ -37,9 +37,11 @@ Public Sub New() _bCol = New M2MBCollection - _bCol.ContainerObject = Me End Sub + Private Sub _bCol_ListChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles _bCol.ListChanged + Me.SetDirtyFlag() + End Sub End Class #End Region |
From: Richard B. <rb...@us...> - 2005-02-14 02:24:27
|
Update of /cvsroot/jcframework/Nunit In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24223 Modified Files: AtomsFramework.xml Nunit_AtomsFramework.vbproj Log Message: Update unit tests for many-to-many and remove old unit tests for previous method of doing N:M associations. Index: Nunit_AtomsFramework.vbproj =================================================================== RCS file: /cvsroot/jcframework/Nunit/Nunit_AtomsFramework.vbproj,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- Nunit_AtomsFramework.vbproj 9 Feb 2005 06:20:47 -0000 1.16 +++ Nunit_AtomsFramework.vbproj 14 Feb 2005 02:24:11 -0000 1.17 @@ -160,21 +160,11 @@ BuildAction = "Compile" /> <File - RelPath = "InheritedClasses\ManyToManyClasses.vb" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "InheritedClasses\ManyToManyClasses_v2.vb" SubType = "Code" BuildAction = "Compile" /> <File - RelPath = "InheritedClasses\ManyToManyTests.vb" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "InheritedClasses\ManyToManyTests_v2.vb" SubType = "Code" BuildAction = "Compile" Index: AtomsFramework.xml =================================================================== RCS file: /cvsroot/jcframework/Nunit/AtomsFramework.xml,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- AtomsFramework.xml 9 Feb 2005 06:20:47 -0000 1.17 +++ AtomsFramework.xml 14 Feb 2005 02:24:11 -0000 1.18 @@ -306,47 +306,6 @@ inverse="false"> <entry fromAttribute="BOID" toAttribute="OIDValue"/> </association> - - <class name="ManyToManyA" table="ManyToManyA" database="MSA" namespace="NunitTests.InheritedClasses"> - <attribute name="GUIDValue" column="GuidValue" key="primary"/> - <attribute name="Description" column="description" /> - <attribute name="M2MABCollection" /> - </class> - <class name="ManyToManyB" table="ManyToManyB" database="MSA" namespace="NunitTests.InheritedClasses"> - <attribute name="GUIDValue" column="GuidValue" key="primary"/> - <attribute name="Description" column="description" /> - <attribute name="M2MABCollection" /> - </class> - <class name="ManyToManyAB" table="ManyToManyAB" database="MSA" namespace="NunitTests.InheritedClasses"> - <attribute name="AGuidValue" column="AGuidValue" key="primary"/> - <attribute name="BGuidValue" column="BGuidValue" key="primary"/> - <attribute name="M2MA"/> - <attribute name="M2MB"/> - </class> - <association fromClass="NunitTests.InheritedClasses.ManyToManyA" - toClass="NunitTests.InheritedClasses.ManyToManyAB" - cardinality="OneToMany" target="M2MABCollection" - retrieveAutomatic="true" saveAutomatic="true" deleteAutomatic="true" inverse="false"> - <entry fromAttribute="GUIDValue" toAttribute="AGuidValue"/> - </association> - <association fromClass="NunitTests.InheritedClasses.ManyToManyB" - toClass="NunitTests.InheritedClasses.ManyToManyAB" - cardinality="OneToMany" target="M2MABCollection" - retrieveAutomatic="true" saveAutomatic="true" deleteAutomatic="true" inverse="false"> - <entry fromAttribute="GUIDValue" toAttribute="BGuidValue"/> - </association> - <association fromClass="NunitTests.InheritedClasses.ManyToManyAB" - toClass="NunitTests.InheritedClasses.ManyToManyA" - cardinality="OneToOne" target="M2MA" - retrieveAutomatic="true" saveAutomatic="true" deleteAutomatic="true" inverse="false"> - <entry fromAttribute="AGuidValue" toAttribute="GUIDValue"/> - </association> - <association fromClass="NunitTests.InheritedClasses.ManyToManyAB" - toClass="NunitTests.InheritedClasses.ManyToManyB" - cardinality="OneToOne" target="M2MB" - retrieveAutomatic="true" saveAutomatic="true" deleteAutomatic="true" inverse="false"> - <entry fromAttribute="BGuidValue" toAttribute="GUIDValue"/> - </association> <class name="LazyEmployee" table="NPEmployee" database="MSA" namespace="NunitTests.StandardClasses"> <attribute name="Name" column="name" find="true" key="primary"/> |
From: Richard B. <rb...@us...> - 2005-02-14 02:23:30
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23624 Modified Files: CAssociationState.vb CCacheEntry.vb CInjectedObject.vb CPersistenceBroker.vb CPersistentCollection.vb CPersistentObject.vb Log Message: Fixes for copying objects to/from the cache and updating many to many associations. Events for collections within an object are now correctly wired to the copied object during the copy instead of either being blank or remaining wired to the original object. Further fixes for cache consistency before and after transaction rollback were also made. ContainerObject property on CPersistentCollection is now marked as obsolete and will probably be removed in a future update. Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.94 retrieving revision 1.95 diff -u -d -r1.94 -r1.95 --- CPersistenceBroker.vb 11 Feb 2005 02:51:35 -0000 1.94 +++ CPersistenceBroker.vb 14 Feb 2005 02:23:10 -0000 1.95 @@ -2538,6 +2538,7 @@ Dim i, k As Integer Dim tmpObj As Object Dim aObj As CAssociationObject + Dim isNewManyToMany As Boolean If obj.IsQueued Then 'if an object has already been added to the save queue, there is no need to add @@ -2639,21 +2640,20 @@ value = tmpObj End If aObj = Nothing - state.ValidateObject(value) + isNewManyToMany = state.ValidateObject(value) For Each qObj In getObjectsToSave(value, True, checkAssociationsRecursivly) queue.Enqueue(qObj) - If aObj Is Nothing AndAlso value.Equals(qObj) Then - 'since we are saving this object (obj) and one of the objects in the association - 'we need to ensure the association table gets updated. This will be done via - 'the CAssociationObject class. We need to create an object here for the class. - aObj = New CAssociationObject - aObj.ObjectA = obj - aObj.ObjectB = value - aObj.Association = udamap - queue.Enqueue(aObj) - End If Next + If isNewManyToMany Then + 'We need to create an association object here for the class. + aObj = New CAssociationObject + aObj.ObjectA = obj + aObj.ObjectB = value + aObj.Association = udamap + queue.Enqueue(aObj) + End If Next k + 'Remove old association records for items removed from the collection state.DoCleanUp() End If End If @@ -3091,7 +3091,7 @@ End Sub Public Shared Sub CopyCollections(ByVal fromObject As IPersistableObject, ByRef toObject As IPersistableObject) - Dim t, iEnumerableType, iListType, iDicType As Type Dim coll, collItem As Object + Dim t, iEnumerableType, iListType, iDicType As Type Dim fromColl, toColl, collItem As Object Dim il As IList Dim id As IDictionary Dim f, fields() As FieldInfo @@ -3108,30 +3108,68 @@ 'Getting the ICloneable interface from the object. If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then Dim IClone As ICloneable = CType(f.GetValue(fromObject.GetSourceObject), ICloneable) - coll = IClone.Clone() + toColl = IClone.Clone() Else - coll = Nothing + toColl = Nothing End If Else - If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + fromColl = f.GetValue(fromObject.GetSourceObject) + If Not fromColl Is Nothing Then '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 + t = f.FieldType + toColl = Activator.CreateInstance(t) 'need to copy references one-by-one + 'Also neeed to connect event handlers of new collection to new object based + 'on event connections of the old collection and the old object + Dim fColl, fieldsColl() As FieldInfo + Dim d, newD, delArray(), newDelArray() As [Delegate] + Dim collDel As MulticastDelegate + While Not t Is Nothing + fieldsColl = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + For Each fColl In fieldsColl + If fColl.FieldType.Name = fColl.Name & "Handler" OrElse fColl.FieldType Is GetType(EventHandler) Then + 'This is an event! + d = fColl.GetValue(fromColl) + collDel = Nothing + If Not d Is Nothing Then + delArray = d.GetInvocationList + For Each d In delArray + If Not d.Target.GetType.GetInterface("IPersistableObject") Is Nothing Then + If CType(d.Target, IPersistableObject).Equals(fromObject.GetSourceObject) Then + newD = MulticastDelegate.CreateDelegate(fColl.FieldType, toObject, d.Method.Name) + If collDel Is Nothing Then + collDel = newD + Else + collDel.Combine(collDel, newD) + End If + End If + End If + Next + fColl.SetValue(toColl, collDel) + End If + End If + Next + If t.IsSubclassOf(GetType(CPersistentCollection)) Then + t = t.BaseType + Else + t = Nothing + End If + End While If Not iListType Is Nothing Then - il = CType(coll, IList) - For Each collItem In f.GetValue(fromObject.GetSourceObject) + il = CType(toColl, IList) + For Each collItem In fromColl il.Add(collItem) Next Else - id = CType(coll, IDictionary) - For Each de As DictionaryEntry In f.GetValue(fromObject.GetSourceObject) + id = CType(toColl, IDictionary) + For Each de As DictionaryEntry In fromColl id.Add(de.Key, de.Value) Next End If Else - coll = Nothing + toColl = Nothing End If End If - f.SetValue(toObject.GetSourceObject, coll) + f.SetValue(toObject.GetSourceObject, toColl) End If Next End Sub End Class \ No newline at end of file Index: CAssociationState.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CAssociationState.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- CAssociationState.vb 11 Feb 2005 02:51:37 -0000 1.1 +++ CAssociationState.vb 14 Feb 2005 02:23:10 -0000 1.2 @@ -179,7 +179,7 @@ AttrMap = keys(i).AttributeMap tmpObj = Nothing Try - tmpObj = obj.GetObjectByAttribute(AttrMap.Name) + tmpObj = obj.GetValueByAttribute(AttrMap.Name) Catch ex As Exception End Try ck.Add(tmpObj) @@ -187,18 +187,23 @@ Return ck End Function - Public Sub ValidateObject(ByVal toObject As IPersistableObject) + Public Function ValidateObject(ByVal toObject As IPersistableObject) As Boolean 'Now we want to find a collection entry which has a matching key signature to the 'passed object. 'This will indicate that the association is still valid, and that we can remove + 'the from/to key pairing from the list of records to delete + ' + 'The function returns true if the object is not in the existing many-to-many association + 'ie we must add it. False indicates the association already exists. + ' If m_association Is Nothing OrElse m_fromObject Is Nothing OrElse toObject Is Nothing Then - Return + Return False End If Dim Keys As CAssociationKeys If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then - Keys = m_association.AssocationTable.FromKeys - Else Keys = m_association.AssocationTable.ToKeys + Else + Keys = m_association.AssocationTable.FromKeys End If Dim objKey As Collection = createKey(toObject, Keys) @@ -219,8 +224,10 @@ Next If found Then m_toClassKeysCollection.Remove(indexToRemove) + Return False End If - End Sub + Return True + End Function Public Sub DoCleanUp() 'Remove records for anything left in the keys collection Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- CCacheEntry.vb 10 Feb 2005 04:22:39 -0000 1.28 +++ CCacheEntry.vb 14 Feb 2005 02:23:10 -0000 1.29 @@ -30,6 +30,7 @@ Private m_object As IPersistableObject Private m_objectCopy As IPersistableObject + Private m_objectCopyAtTransactionStart As IPersistableObject Private m_transactionType As CCacheEntry.CacheTransaction Private m_expiryTime As Date Private m_originalObject As IPersistableObject @@ -115,68 +116,77 @@ End Property Public Sub CopyObject() + 'Need two object copies + 'One for the copy made at the very start of the transaction + 'One for any updates made to the object (via save) during the transaction so that + ' cache reads get the correct copy + m_objectCopy = m_object.Copy + m_objectCopyAtTransactionStart = m_object.Copy + End Sub + + Public Sub UpdateObject() m_objectCopy = m_object.Copy End Sub Public Sub RestoreObject() - m_object = m_objectCopy - End Sub + m_object = m_objectCopyAtTransactionStart + End Sub - 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 + ' 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) - 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. - If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then - Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) - coll = IClone.Clone() - Else - coll = Nothing - End If - Else - If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then - '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 - Else - coll = Nothing - End If - End If - m_collectionCollection.Add(f.Name, coll) End If Next - End Sub + ' '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) + ' 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. + ' If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then + ' Dim IClone As ICloneable = CType(f.GetValue(m_object.GetSourceObject), ICloneable) + ' coll = IClone.Clone() + ' Else + ' coll = Nothing + ' End If + ' Else + ' If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then + ' '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 + ' Else + ' coll = Nothing + ' End If + ' End If + ' m_collectionCollection.Add(f.Name, coll) ' End If ' Next + 'End Sub - 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) - 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 + '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) + ' 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 Public Sub New(ByVal lifetime As Double) m_expiryTime = DateAdd(DateInterval.Minute, lifetime, Now) @@ -621,7 +631,6 @@ End If If obj.GetClassMap.RelationalDatabase.getConnection(Nothing).Started Then ce.TransactionType = CCacheEntry.CacheTransaction.Saved - ce.CopyObject() End If Try ce.OriginalObject = obj @@ -907,16 +916,23 @@ 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 + If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then + Select Case ce.TransactionType + Case CCacheEntry.CacheTransaction.None + 'Even though an object hasn't been saved/deleted it may still have been + 'modified so we must restore it in any case + ce.RestoreObject() + Case CCacheEntry.CacheTransaction.Deleted + 'Lets cancel deletes first - just means resetting transaction to None + ce.TransactionType = CCacheEntry.CacheTransaction.None + 'ce.RestoreCollections() + ce.RestoreObject() + Case CCacheEntry.CacheTransaction.Saved + 'Now look for cache entries to be saved and restore them + ce.RestoreObject() + 'ce.RestoreCollections() + ce.TransactionType = CCacheEntry.CacheTransaction.None + End Select End If Next @@ -940,7 +956,8 @@ For Each x In Me ce = x.Value If ce.PersistentObject.GetClassMap.RelationalDatabase Is reldb Then - ce.CopyCollections() + 'ce.CopyCollections() + ce.CopyObject() End If Next End Sub Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- CInjectedObject.vb 11 Feb 2005 02:51:35 -0000 1.12 +++ CInjectedObject.vb 14 Feb 2005 02:23:10 -0000 1.13 @@ -76,15 +76,19 @@ End If Dim f, fields() As FieldInfo Dim value As Object - Dim t As Type - Try + Dim t, iListType, iDicType As Type Try t = sourceObject.GetType While Not t Is Nothing fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) 'Note that this will copy event handlers as well For Each f In fields - value = f.GetValue(sourceObject) - f.SetValue(targetObject, value) + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + 'Do not copy collections yet - we'll do that at the end + If iListType Is Nothing AndAlso iDicType Is Nothing Then + value = f.GetValue(sourceObject) + f.SetValue(targetObject, value) + End If Next If Not t.BaseType Is Nothing Then t = t.BaseType @@ -92,7 +96,7 @@ t = Nothing End If End While - Catch ex As Exception + CPersistenceBroker.CopyCollections(sourceObject, targetObject) Catch ex As Exception Debug.WriteLine(ex.Message) End Try End Sub Index: CPersistentCollection.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentCollection.vb,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- CPersistentCollection.vb 21 Dec 2004 21:57:12 -0000 1.15 +++ CPersistentCollection.vb 14 Feb 2005 02:23:11 -0000 1.16 @@ -1,5 +1,7 @@ Option Explicit On Imports System.ComponentModel +Imports System.Reflection + '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CPersistentCollection @@ -21,6 +23,7 @@ Inherits CollectionBase Implements IComponent Implements IBindingList + 'Implements ICloneable Private m_container As CPersistentObject @@ -41,7 +44,8 @@ ''' [rbanks] 17/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- - <Browsable(False)> Public Property ContainerObject() As CPersistentObject + <Browsable(False), Obsolete("Changes in collection management have made this obsolete. Please use the ListChanged event for equivalent functionality")> _ + Public Property ContainerObject() As CPersistentObject Get Return m_container End Get @@ -195,10 +199,10 @@ Private Sub ItemDirtiedHandler(ByVal sender As Object, ByVal e As EventArgs) ' Debug.WriteLine("Collection trapped item dirtied event for " & sender.GetType.Name) RaiseEvent ItemDirtied(Me, e) - If Not Me.ContainerObject Is Nothing Then - 'Debug.WriteLine("item dirtied - dirtying container") - ContainerObject.SetDirtyFlag() - End If + 'If Not Me.ContainerObject Is Nothing Then + ' 'Debug.WriteLine("item dirtied - dirtying container") + ' ContainerObject.SetDirtyFlag() + 'End If End Sub #End Region @@ -297,7 +301,6 @@ End Sub Protected Overrides Sub OnClearComplete() - ' Debug.WriteLine("CPColl clear complete") RaiseEvent ListChanged(Me, New ListChangedEventArgs(ListChangedType.Reset, 0)) End Sub @@ -342,4 +345,49 @@ RaiseEvent Disposed(Me, EventArgs.Empty) End Sub #End Region + + '#Region "ICloneable Interface" + ' Public Function Clone() As Object Implements System.ICloneable.Clone + ' Dim obj As CPersistentCollection + ' 'obj = Me.MemberwiseClone + ' 'Use reflection to copy all of the fields from Obj to me (by value) + ' Dim f, fields() As FieldInfo + ' Dim e, events() As EventInfo + ' Dim value As Object + ' Dim t As Type + ' Dim d, newD, delArray() As [Delegate] + ' Try + ' t = Me.GetType + ' obj = Activator.CreateInstance(t) + ' While Not t Is Nothing + ' fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + ' 'Note that this will copy event handlers as well + ' For Each f In fields + ' If f.FieldType.Name = f.Name & "Handler" Then + ' 'This is an event! + ' d = f.GetValue(Me) + ' If Not d Is Nothing Then + ' delArray = d.GetInvocationList + ' For Each d In delArray + ' If d.Target.Equals(obj) Then + ' newD = [Delegate].CreateDelegate(f.FieldType, obj, d.Target) + ' End If + ' Next + ' End If + ' End If + ' value = f.GetValue(Me) + ' f.SetValue(obj, value) + ' Next + ' If t.IsSubclassOf(GetType(CPersistentCollection)) Then + ' t = t.BaseType + ' Else + ' t = Nothing + ' End If + ' End While + ' Catch ex As Exception + ' Debug.WriteLine(ex.Message) + ' End Try + ' Return obj + ' End Function + '#End Region End Class Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.54 retrieving revision 1.55 diff -u -d -r1.54 -r1.55 --- CPersistentObject.vb 11 Feb 2005 02:51:37 -0000 1.54 +++ CPersistentObject.vb 14 Feb 2005 02:23:11 -0000 1.55 @@ -675,7 +675,7 @@ Return CallByName(o, propertyName, CallType.Get) End If Catch err As Exception - Throw New Exception("getCollectionByAttribute failed", err) + Throw New Exception("getCollectionByAttribute failed for class " & me.getclassmap.name & " attribute: " & " " & pname, err) End Try End Function @@ -1238,10 +1238,14 @@ '''----------------------------------------------------------------------------- Public Overridable Function Copy() As IPersistableObject Implements IPersistentObject.Copy Dim obj As CPersistentObject - obj = CType(Me.MemberwiseClone, CPersistentObject) + obj = Me.getClassMap.CreateObjectInstance + obj.ReplaceWith(Me) + 'obj = CType(Me.MemberwiseClone, CPersistentObject) 'Because memberwise clone only reference copies collections we should also 'copy the collections as well, since failing to do so can corrupt the cache. - CPersistenceBroker.CopyCollections(Me, obj) Return obj + 'This will also connect events from the collections to the new object based on + 'existing event handlers in "Me" + 'CPersistenceBroker.CopyCollections(Me, obj) Return obj End Function '''----------------------------------------------------------------------------- @@ -1258,22 +1262,26 @@ '''----------------------------------------------------------------------------- Public Overridable Sub ReplaceWith(ByVal obj As IPersistableObject) Implements IPersistentObject.ReplaceWith 'Use reflection to copy all of the fields from Obj to me (by value) + 'Also copy collections If obj Is Nothing Then Return If Not obj.GetObjectType Is Me.GetObjectType Then Throw New Exception("Objects must be of the same type") End If Dim f, fields() As FieldInfo Dim value As Object - Dim t As Type - Try + Dim t, iListType, iDicType As Type Try t = Me.GetType While Not t Is Nothing fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) 'Note that this will copy event handlers as well For Each f In fields - ' Debug.WriteLine(f.Name) - value = f.GetValue(obj) - f.SetValue(Me, value) + iListType = f.FieldType.GetInterface("IList", True) + iDicType = f.FieldType.GetInterface("IDictionary", True) + 'Do not copy collections yet - we'll do that at the end + If iListType Is Nothing AndAlso iDicType Is Nothing Then + value = f.GetValue(obj) + f.SetValue(Me, value) + End If Next If t.IsSubclassOf(GetType(CPersistentObject)) Then t = t.BaseType @@ -1281,7 +1289,7 @@ t = Nothing End If End While - Catch ex As Exception + CPersistenceBroker.CopyCollections(obj, Me) Catch ex As Exception Debug.WriteLine(ex.Message) End Try End Sub @@ -1675,37 +1683,37 @@ Return obj End Function - <EditorBrowsable(EditorBrowsableState.Advanced)> _ - Public Overridable Function GetBaseCopy() As CPersistentObject - 'Use reflection to copy all of the fields from Obj to me (by value) - If Me.getClassMap.SuperClass Is Nothing Then - Return Nothing - End If - Dim obj As CPersistentObject = Me.getClassMap.SuperClass.CreateObjectInstance - Dim f, fields() As FieldInfo - Dim value As Object - Dim t As Type - Try - t = obj.GetType - While Not t Is Nothing - fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) - 'Note that this will copy event handlers as well - For Each f In fields - value = f.GetValue(Me) - f.SetValue(obj, value) - Next - If t.IsSubclassOf(GetType(CPersistentObject)) Then - t = t.BaseType - Else - t = Nothing - End If - End While - Return obj - Catch ex As Exception - Debug.WriteLine(ex.Message) - End Try - Return Nothing - End Function + '<EditorBrowsable(EditorBrowsableState.Advanced)> _ + 'Public Overridable Function GetBaseCopy() As CPersistentObject + ' 'Use reflection to copy all of the fields from Obj to me (by value) + ' If Me.getClassMap.SuperClass Is Nothing Then + ' Return Nothing + ' End If + ' Dim obj As CPersistentObject = Me.getClassMap.SuperClass.CreateObjectInstance + ' Dim f, fields() As FieldInfo + ' Dim value As Object + ' Dim t As Type + ' Try + ' t = obj.GetType + ' While Not t Is Nothing + ' fields = t.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public) + ' 'Note that this will copy event handlers as well + ' For Each f In fields + ' value = f.GetValue(Me) + ' f.SetValue(obj, value) + ' Next + ' If t.IsSubclassOf(GetType(CPersistentObject)) Then + ' t = t.BaseType + ' Else + ' t = Nothing + ' End If + ' End While + ' Return obj + ' Catch ex As Exception + ' Debug.WriteLine(ex.Message) + ' End Try + ' Return Nothing + 'End Function #End Region |
From: Richard B. <rb...@us...> - 2005-02-11 02:53:29
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25275/InheritedClasses Modified Files: AtomsFrameworkTests.vb ManyToManyTests_v2.vb Log Message: Units tests for new many-to-many associations Index: ManyToManyTests_v2.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/ManyToManyTests_v2.vb,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- ManyToManyTests_v2.vb 10 Feb 2005 04:23:48 -0000 1.2 +++ ManyToManyTests_v2.vb 11 Feb 2005 02:53:20 -0000 1.3 @@ -141,5 +141,38 @@ Assert.AreEqual(0, c.ResultSet.ResultSet.Tables(0).Rows.Count) End Sub + <Test()> Public Sub RemoveFromCollection() + Dim gvalA, gvalB As String + Dim s As String + A = New M2MA + A.Description = "A1" + gvalA = A.GUIDValue + B = New M2MB + B.Description = "B1" + gvalB = B.GUIDValue + A.M2MBCollection.Add(B) + B.M2MACollection.Add(A) + A.Save() + pbroker.ClearCache() + A = New M2MA + A.GUIDValue = gvalA + A.Retrieve() + Assert.IsTrue(A.Persistent) + 'Being bi-directional this should result in both A/B objects having empty collections + A.M2MBCollection.Remove(0) + A.Save() + pbroker.ClearCache() + A = New M2MA + A.GUIDValue = gvalA + A.Retrieve() + B = New M2MB + B.GUIDValue = gvalB + B.Retrieve() + Assert.IsTrue(A.Persistent) + Assert.IsTrue(B.Persistent) + Assert.AreEqual(0, A.M2MBCollection.Count) + Assert.AreEqual(0, B.M2MACollection.Count) + End Sub + End Class End Namespace \ No newline at end of file Index: AtomsFrameworkTests.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/AtomsFrameworkTests.vb,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- AtomsFrameworkTests.vb 7 Feb 2005 22:07:16 -0000 1.13 +++ AtomsFrameworkTests.vb 11 Feb 2005 02:53:20 -0000 1.14 @@ -539,6 +539,45 @@ Assert.AreEqual("bb42", CType(a1.TableBCollection.Item(1), TableB).Id) End Sub + <Test()> Public Sub CheckCacheAfterRollback5() + 'Modify but don't save an object during a transaction + Dim a As New TableA + Dim b As New TableB + Dim a1 As New TableA + a.Id = "aa5" + b.Id = "bb51" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb52" + b.TableA = a + a.TableBCollection.Add(b) + a.Save() + Assert.AreEqual(2, a.TableBCollection.Count) + pbroker.startTransaction() + a1.Id = "aa5" + a1.Retrieve() + Assert.AreEqual(2, a1.TableBCollection.Count) + b = New TableB + b.Id = "bb53" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb54" + b.TableA = a + a.TableBCollection.Add(b) + b = a.TableBCollection.Item(1) + Assert.AreEqual("bb52", b.Id) + a.TableBCollection.Remove(1) + Assert.AreEqual(3, a.TableBCollection.Count) + 'Now abort the transaction + pbroker.rollback() + a1 = New TableA + a1.Id = "aa5" + a1.Retrieve() 'Will get from cache + Assert.AreEqual(2, a1.TableBCollection.Count) + Assert.AreEqual("bb52", CType(a1.TableBCollection.Item(1), TableB).Id) + End Sub End Class End Namespace \ No newline at end of file |
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24463 Modified Files: AToMSFramework.vbproj CAssociationObject.vb CClassMap.vb CInjectedObject.vb CPersistenceBroker.vb CPersistentObject.vb Added Files: CAssociationState.vb Log Message: Many-to-Many associations now working (for Inherited objects and XML mapping only at this stage). Also includes a number of other minor fixes. Index: AToMSFramework.vbproj =================================================================== RCS file: /cvsroot/jcframework/dotnet/AToMSFramework.vbproj,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- AToMSFramework.vbproj 9 Feb 2005 06:24:44 -0000 1.23 +++ AToMSFramework.vbproj 11 Feb 2005 02:51:35 -0000 1.24 @@ -119,6 +119,11 @@ BuildAction = "Compile" /> <File + RelPath = "CAssociationState.vb" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "CAssociationTable.vb" SubType = "Code" BuildAction = "Compile" Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.93 retrieving revision 1.94 diff -u -d -r1.93 -r1.94 --- CPersistenceBroker.vb 10 Feb 2005 04:22:39 -0000 1.93 +++ CPersistenceBroker.vb 11 Feb 2005 02:51:35 -0000 1.94 @@ -551,7 +551,7 @@ End If 'Check whether the object is of child type - If fromClass.ChildrenMaps.Count > 0 Then + If toClass.ChildrenMaps.Count > 0 Then targetobj = Me.createTargetObjectForMultipleInheritance(toClass, obj.GetObjectType, obj.GetObjectType.Namespace, rs.ResultSet.Tables(0).Rows(i), joins, conn) 'update classMapCount with the child count number classMapCount += Me.getChildCountForMultipleInheritance(toClass) @@ -1150,6 +1150,7 @@ deletePrivateObject(Value, conn, True) End If End If + cm = clMap End If obj.Persistent = False @@ -2446,6 +2447,7 @@ cm2 = classMap While Not cm1 Is Nothing classMap.populateObject(cm1, obj, dataRow, joins.GetTableAlias(cm1), True, classMap) + 'classMap.populateObject(cm1, obj, dataRow, joins.GetTableAlias(cm1), True, cm1) cm2 = cm1 cm1 = cm1.SuperClass End While @@ -2588,10 +2590,6 @@ End If End If - 'If includeBaseObject Then Stack.Push(obj) - ''Clear the dirty flag to prevent recursion in the class structure causing an infinite loop - 'obj.IsDirty = False - 'Now process the object associations to see what else needs saving cm = obj.GetClassMap() @@ -2628,6 +2626,10 @@ col = obj.GetCollectionByAttribute(udamap.ToClassTarget) End If End If + 'To ensure consistency of the association we need to get a list of records in the mapping table + 'and check wether the record is still valid. Removal of an object from a collection + 'should mean that we have to delete the associationtable record. + Dim state As New CAssociationState(obj, udamap) If Not col Is Nothing Then For k = 0 To col.Count() - 1 tmpObj = col.Item(k) @@ -2637,6 +2639,7 @@ value = tmpObj End If aObj = Nothing + state.ValidateObject(value) For Each qObj In getObjectsToSave(value, True, checkAssociationsRecursivly) queue.Enqueue(qObj) If aObj Is Nothing AndAlso value.Equals(qObj) Then @@ -2651,6 +2654,7 @@ End If Next Next k + state.DoCleanUp() End If End If End If @@ -3085,4 +3089,49 @@ vbCrLf & ex.Message) End Try End Sub + + Public Shared Sub CopyCollections(ByVal fromObject As IPersistableObject, ByRef toObject As IPersistableObject) + Dim t, iEnumerableType, iListType, iDicType As Type Dim coll, collItem As Object + Dim il As IList + Dim id As IDictionary + Dim f, fields() As FieldInfo + Dim value As Object + + t = fromObject.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) + 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. + If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + Dim IClone As ICloneable = CType(f.GetValue(fromObject.GetSourceObject), ICloneable) + coll = IClone.Clone() + Else + coll = Nothing + End If + Else + If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + '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 collItem In f.GetValue(fromObject.GetSourceObject) + il.Add(collItem) + Next + Else + id = CType(coll, IDictionary) + For Each de As DictionaryEntry In f.GetValue(fromObject.GetSourceObject) + id.Add(de.Key, de.Value) + Next + End If + Else + coll = Nothing + End If + End If + f.SetValue(toObject.GetSourceObject, coll) + End If Next + End Sub End Class \ No newline at end of file --- NEW FILE: CAssociationState.vb --- 'Class to record the current state of many-to-many associations and to handle 'changes to that state (such as objects being removed from collections) 'To use this class, instantiate it with an object 'Pass in objects in the many-to-many collection via the ValidateObject method 'Call the collectionCleanup cause the orphaned association table records to be deleted Friend Class CAssociationState Private m_toClassKeysCollection As New Collection Private m_fromObject As IPersistableObject Private m_association As CUDAMap Private m_fromClass As CClassMap Private m_toClass As CClassMap Public Property FromObject() As IPersistableObject Get Return m_fromObject End Get Set(ByVal Value As IPersistableObject) m_fromObject = Value If Not m_association Is Nothing Then If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then m_fromClass = m_association.FromClass m_toClass = m_association.ToClass Else m_fromClass = m_association.ToClass m_toClass = m_association.FromClass End If End If End Set End Property Public Property Association() As CUDAMap Get Return m_association End Get Set(ByVal Value As CUDAMap) If Value.Cardinality <> CUDAMap.CardinalityEnum.MANY_TO_MANY Then m_association = Nothing Exit Property End If m_association = Value If Not m_fromObject Is Nothing Then If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then m_fromClass = m_association.FromClass m_toClass = m_association.ToClass Else m_fromClass = m_association.ToClass m_toClass = m_association.FromClass End If End If End Set End Property Public Sub LoadState() If m_fromObject Is Nothing Then Exit Sub If m_association Is Nothing Then Exit Sub Dim db As CRelationalDatabase Dim key As CAssociationKey Dim fromKeys As CAssociationKeys Dim toKeys As CAssociationKeys Dim paramCount As Integer Dim conn As _CConnection If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then fromKeys = m_association.AssocationTable.FromKeys toKeys = m_association.AssocationTable.ToKeys Else toKeys = m_association.AssocationTable.FromKeys fromKeys = m_association.AssocationTable.ToKeys End If m_toClassKeysCollection = New Collection db = m_fromObject.GetClassMap.RelationalDatabase conn = db.getConnection(Nothing) 'To load the state we need to hit the database to determine what the records are in the 'association table that match the from class key values 'We will then store the toClass values as a collection of objects in the keys collection 'STEP 1. Build SQL for retrieving the records Dim statement As New CSqlStatement statement.addSqlClause(db.getClauseStringSelect) statement.addSqlClause(" ") Dim isFirst As Boolean = True Dim i As Short For i = 0 To toKeys.Count - 1 If isFirst Then isFirst = False Else statement.addSqlClause(", ") End If key = toKeys(i) statement.addSqlClause(key.ColumnMap.getFullyQualifiedName) Next i 'Add the FROM clause to the statement statement.addSqlClause(" " & db.getClauseStringFrom & " ") statement.addSqlClause(m_association.AssocationTable.Name) statement.addSqlClause(" " & db.getClauseStringWhere & " ") 'Add the clause "WHERE key=?" to the selectStatement paramCount = 1 isFirst = True For i = 0 To fromKeys.Count - 1 key = fromKeys(i) If Not isFirst Then statement.addSqlClause(" " & db.getClauseStringAnd & " ") End If isFirst = False statement.addSqlClause(key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) statement.addSqlParameter(paramCount, m_fromObject.GetValueByAttribute(key.AttributeMap.Name), key.ColumnMap) paramCount += 1 Next i Dim x As String = statement.SqlString Dim p As CSQLParameter For i = 1 To paramCount - 1 p = statement.Parameters.Item(i) If IsNullAlias(p.Value) Then If db.UseANSINulls = True Then x = x.Replace(" = _" & i.ToString & "_", " is NULL") p.Ignore = True Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Next statement.SqlString = x 'STEP 2. Execute Statement and Create CacheKeys Dim rs As CResultset Try getPersistenceBrokerInstance.PCSQLHits.Increment() Catch End Try rs = conn.processSelectStatement(statement) Debug.WriteLine("Select statement returned " & rs.ResultSet.Tables(0).Rows.Count & " row(s)") If rs.ResultSet.Tables(0).Rows.Count = 0 Then 'No records means nothing to do so lets leave Return End If For Each rw As DataRow In rs.ResultSet.Tables(0).Rows m_toClassKeysCollection.Add(createKey(rw, toKeys)) Next End Sub Private Function createKey(ByVal rw As DataRow, ByVal keys As CAssociationKeys) As Collection Dim ck As New Collection Dim tmpObj As Object Dim AttrMap As CAttributeMap Dim i As Integer For i = 0 To keys.Count - 1 'Attempt to load column via alias first, then table qualified name then column name tmpObj = Nothing Try If rw.Table.Columns.Contains(keys(i).ColumnMap.Name) Then tmpObj = rw.Item(keys(i).ColumnMap.Name) End If Catch ex As Exception End Try ck.Add(tmpObj) Next i Return ck End Function Private Function createKey(ByVal obj As IPersistableObject, ByVal keys As CAssociationKeys) As Collection Dim ck As New Collection Dim tmpObj As Object Dim AttrMap As CAttributeMap Dim i As Integer For i = 0 To keys.Count - 1 AttrMap = keys(i).AttributeMap tmpObj = Nothing Try tmpObj = obj.GetObjectByAttribute(AttrMap.Name) Catch ex As Exception End Try ck.Add(tmpObj) Next i Return ck End Function Public Sub ValidateObject(ByVal toObject As IPersistableObject) 'Now we want to find a collection entry which has a matching key signature to the 'passed object. 'This will indicate that the association is still valid, and that we can remove If m_association Is Nothing OrElse m_fromObject Is Nothing OrElse toObject Is Nothing Then Return End If Dim Keys As CAssociationKeys If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then Keys = m_association.AssocationTable.FromKeys Else Keys = m_association.AssocationTable.ToKeys End If Dim objKey As Collection = createKey(toObject, Keys) Dim col As Collection Dim indexToRemove As Integer Dim found As Boolean For n As Integer = 1 To m_toClassKeysCollection.Count col = m_toClassKeysCollection(n) found = True For i As Integer = 1 To col.Count If Not col(i).Equals(objKey(i)) Then found = False Exit For End If Next If found Then indexToRemove = n Exit For Next If found Then m_toClassKeysCollection.Remove(indexToRemove) End If End Sub Public Sub DoCleanUp() 'Remove records for anything left in the keys collection Dim col As Collection 'Need to build the main delete statement then call it multiple times 'changing the where clause each time. Dim isFirst As Boolean Dim db As _CRelationalDatabase Dim m_deleteStatement As New CSqlStatement Dim m_actualStatement As CSqlStatement Dim paramCount, fromOffset As Integer Dim AttrMap As CAttributeMap Dim Key As CAssociationKey Dim fromKeys, toKeys As CAssociationKeys Dim i As Short Dim conn As _CConnection If m_fromObject Is Nothing Then Return End If If m_toClassKeysCollection.Count = 0 Then Exit Sub End If db = m_fromObject.GetClassMap.RelationalDatabase conn = db.getConnection(Nothing) 'Determine which order classes are in If m_fromObject.GetClassMap.Name = m_association.FromClass.Name Then fromKeys = m_association.AssocationTable.FromKeys toKeys = m_association.AssocationTable.ToKeys Else toKeys = m_association.AssocationTable.FromKeys fromKeys = m_association.AssocationTable.ToKeys End If m_deleteStatement.addSqlClause(db.getClauseStringDelete & " " & db.getClauseStringFrom & " ") m_deleteStatement.addSqlClause(m_association.AssocationTable.Name & " ") m_deleteStatement.addSqlClause(db.getClauseStringWhere & " ") paramCount = 1 isFirst = True For i = 0 To fromKeys.Count - 1 Key = fromKeys(i) If Not isFirst Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If isFirst = False m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) m_deleteStatement.addSqlParameter(paramCount, m_fromObject.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i fromOffset = paramCount - 1 For i = 0 To toKeys.Count - 1 Key = toKeys(i) If Not isFirst Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If isFirst = False m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) paramCount += 1 Next i For n As Integer = 1 To m_toClassKeysCollection.Count m_actualStatement = m_deleteStatement col = m_toClassKeysCollection(n) For i = 1 To toKeys.Count m_actualStatement.addSqlParameter(fromOffset + i, col.Item(i), toKeys(i - 1).ColumnMap) Next Dim x As String = m_actualStatement.SqlString Dim p As CSQLParameter For i = 1 To paramCount - 1 p = m_actualStatement.Parameters.Item(i) If IsNullAlias(p.Value) Then If db.UseANSINulls = True Then x = x.Replace(" = _" & i.ToString & "_", " is NULL") p.Ignore = True Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Next m_actualStatement.SqlString = x Try 'May have already been deleted by other side of association conn.processStatement(m_actualStatement) Catch ex As Exception End Try Next End Sub Public Sub New(ByVal obj As IPersistableObject, ByVal udamap As CUDAMap) m_fromObject = obj m_association = udamap LoadState() End Sub End Class Index: CAssociationObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CAssociationObject.vb,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- CAssociationObject.vb 10 Feb 2005 04:22:39 -0000 1.2 +++ CAssociationObject.vb 11 Feb 2005 02:51:35 -0000 1.3 @@ -305,4 +305,5 @@ Next End If End Sub + End Class Index: CClassMap.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CClassMap.vb,v retrieving revision 1.49 retrieving revision 1.50 diff -u -d -r1.49 -r1.50 --- CClassMap.vb 9 Feb 2005 06:24:44 -0000 1.49 +++ CClassMap.vb 11 Feb 2005 02:51:35 -0000 1.50 @@ -1406,7 +1406,8 @@ skipAttribute = False If checkForDuplicateAttributes Then Try - If Not classMapToCheck.getAttributeMapByString(AttrMap.Name, False) Is Nothing Then + 'If Not classMapToCheck.getAttributeMapByString(AttrMap.Name, False) Is Nothing Then + If Not classMapToCheck.getAttributeMapByString(AttrMap.Name, True) Is Nothing Then skipAttribute = True End If Catch @@ -1500,7 +1501,8 @@ skipAttribute = False If checkForDuplicateAttributes Then Try - If Not classMapToCheck.getAttributeMapByString(AttrMap.Name, False) Is Nothing Then + 'If Not classMapToCheck.getAttributeMapByString(AttrMap.Name, False) Is Nothing Then + If Not classMapToCheck.getAttributeMapByString(AttrMap.Name, True) Is Nothing Then skipAttribute = True End If Catch Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- CInjectedObject.vb 9 Feb 2005 06:24:44 -0000 1.11 +++ CInjectedObject.vb 11 Feb 2005 02:51:35 -0000 1.12 @@ -550,12 +550,11 @@ End Function Public Function Copy() As IPersistableObject Implements IPersistableObject.Copy - 'Dim m_object2 As Object Dim injobj As CInjectedObject injobj = CType(Me.MemberwiseClone, CInjectedObject) - 'm_object2 = Activator.CreateInstance(m_object.GetType) - 'ReplaceValues(m_object, m_object2) - 'injobj = New CInjectedObject(m_object2) + 'Because memberwise clone only reference copies collections we should also + 'copy the collections as well, since failing to do so can corrupt the cache. + CPersistenceBroker.CopyCollections(Me, injobj) Return injobj End Function Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.53 retrieving revision 1.54 diff -u -d -r1.53 -r1.54 --- CPersistentObject.vb 9 Feb 2005 06:24:44 -0000 1.53 +++ CPersistentObject.vb 11 Feb 2005 02:51:37 -0000 1.54 @@ -1237,7 +1237,11 @@ ''' </history> '''----------------------------------------------------------------------------- Public Overridable Function Copy() As IPersistableObject Implements IPersistentObject.Copy - Return Me.MemberwiseClone + Dim obj As CPersistentObject + obj = CType(Me.MemberwiseClone, CPersistentObject) + 'Because memberwise clone only reference copies collections we should also + 'copy the collections as well, since failing to do so can corrupt the cache. + CPersistenceBroker.CopyCollections(Me, obj) Return obj End Function '''----------------------------------------------------------------------------- |
From: Richard B. <rb...@us...> - 2005-02-10 22:43:06
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23935/InheritedClasses Modified Files: Tag: v2_0 AtomsFrameworkTests.vb Log Message: Unit test for checking collection of cached objects after rollback Index: AtomsFrameworkTests.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/AtomsFrameworkTests.vb,v retrieving revision 1.11.2.2 retrieving revision 1.11.2.3 diff -u -d -r1.11.2.2 -r1.11.2.3 --- AtomsFrameworkTests.vb 7 Feb 2005 22:05:52 -0000 1.11.2.2 +++ AtomsFrameworkTests.vb 10 Feb 2005 22:42:56 -0000 1.11.2.3 @@ -539,6 +539,45 @@ Assert.AreEqual("bb42", CType(a1.TableBCollection.Item(1), TableB).Id) End Sub + <Test()> Public Sub CheckCacheAfterRollback5() + 'Modify but don't save an object during a transaction + Dim a As New TableA + Dim b As New TableB + Dim a1 As New TableA + a.Id = "aa5" + b.Id = "bb51" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb52" + b.TableA = a + a.TableBCollection.Add(b) + a.Save() + Assert.AreEqual(2, a.TableBCollection.Count) + pbroker.startTransaction() + a1.Id = "aa5" + a1.Retrieve() + Assert.AreEqual(2, a1.TableBCollection.Count) + b = New TableB + b.Id = "bb53" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb54" + b.TableA = a + a.TableBCollection.Add(b) + b = a.TableBCollection.Item(1) + Assert.AreEqual("bb52", b.Id) + a.TableBCollection.Remove(1) + Assert.AreEqual(3, a.TableBCollection.Count) + 'Now abort the transaction + pbroker.rollback() + a1 = New TableA + a1.Id = "aa5" + a1.Retrieve() 'Will get from cache + Assert.AreEqual(2, a1.TableBCollection.Count) + Assert.AreEqual("bb52", CType(a1.TableBCollection.Item(1), TableB).Id) + End Sub End Class End Namespace \ No newline at end of file |
From: Richard B. <rb...@us...> - 2005-02-10 22:42:23
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23558 Modified Files: Tag: v2_0 CCacheEntry.vb CInjectedObject.vb CPersistenceBroker.vb CPersistentObject.vb Log Message: Ensure that collections are deep copied not reference copied when persistent objects are copied (ie in the cache, and via the copy method). Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.89.2.1 retrieving revision 1.89.2.2 diff -u -d -r1.89.2.1 -r1.89.2.2 --- CPersistenceBroker.vb 6 Feb 2005 02:48:36 -0000 1.89.2.1 +++ CPersistenceBroker.vb 10 Feb 2005 22:42:11 -0000 1.89.2.2 @@ -1831,6 +1831,28 @@ End Function + Public Function ProcessPureSQL(ByVal inSQL As String, ByVal conn As _CConnection) As CCursor + Dim statement As New CSqlStatement + statement.SqlString = inSQL + + Try + PCSQLHits.Increment() + Catch + End Try + + Dim cursor As CCursor + Dim rs As CResultset + rs = conn.processSelectStatement(statement) + + cursor = New CCursor + cursor.ParentCriteria = Nothing + cursor.ResultSet = rs + cursor.ClassMap = Nothing + cursor.HoldsProxies = False + Return cursor + End Function + + '''----------------------------------------------------------------------------- ''' <summary> ''' Initiates a transaction on all database connections. @@ -2948,4 +2970,52 @@ vbCrLf & ex.Message) End Try End Sub + + Public Shared Sub CopyCollections(ByVal fromObject As IPersistableObject, ByRef toObject As IPersistableObject) + Dim t, iEnumerableType, iListType, iDicType As Type + Dim coll, collItem As Object + Dim il As IList + Dim id As IDictionary + Dim f, fields() As FieldInfo + Dim value As Object + + t = fromObject.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) + 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. + If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + Dim IClone As ICloneable = CType(f.GetValue(fromObject.GetSourceObject), ICloneable) + coll = IClone.Clone() + Else + coll = Nothing + End If + Else + If Not f.GetValue(fromObject.GetSourceObject) Is Nothing Then + '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 collItem In f.GetValue(fromObject.GetSourceObject) + il.Add(collItem) + Next + Else + id = CType(coll, IDictionary) + For Each de As DictionaryEntry In f.GetValue(fromObject.GetSourceObject) + id.Add(de.Key, de.Value) + Next + End If + Else + coll = Nothing + End If + End If + f.SetValue(toObject, coll) + End If + Next + End Sub End Class \ No newline at end of file Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.25.2.2 retrieving revision 1.25.2.3 diff -u -d -r1.25.2.2 -r1.25.2.3 --- CCacheEntry.vb 6 Feb 2005 02:48:36 -0000 1.25.2.2 +++ CCacheEntry.vb 10 Feb 2005 22:42:11 -0000 1.25.2.3 @@ -123,14 +123,21 @@ End Sub Public Sub CopyCollections() - Dim t, iEnumerableType, iListType, iDicType As Type Dim coll, obj As Object + 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 + '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) @@ -148,7 +155,8 @@ Else If Not f.GetValue(m_object.GetSourceObject) Is Nothing Then '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 + 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) @@ -164,19 +172,26 @@ coll = Nothing End If End If - m_collectionCollection.Add(f.Name, coll) End If Next + m_collectionCollection.Add(f.Name, coll) + End If + Next End Sub Public Sub RestoreCollections() - Dim t, iEnumerableType, iListType, iDicType As Type Dim f, fields() As FieldInfo + 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 + '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 Public Sub New(ByVal lifetime As Double) Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.9.2.1 retrieving revision 1.9.2.2 diff -u -d -r1.9.2.1 -r1.9.2.2 --- CInjectedObject.vb 4 Feb 2005 04:46:08 -0000 1.9.2.1 +++ CInjectedObject.vb 10 Feb 2005 22:42:11 -0000 1.9.2.2 @@ -550,12 +550,11 @@ End Function Public Function Copy() As IPersistableObject Implements IPersistableObject.Copy - 'Dim m_object2 As Object Dim injobj As CInjectedObject injobj = CType(Me.MemberwiseClone, CInjectedObject) - 'm_object2 = Activator.CreateInstance(m_object.GetType) - 'ReplaceValues(m_object, m_object2) - 'injobj = New CInjectedObject(m_object2) + 'Because memberwise clone only reference copies collections we should also + 'copy the collections as well, since failing to do so can corrupt the cache. + CPersistenceBroker.CopyCollections(Me, injobj) Return injobj End Function Index: CPersistentObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistentObject.vb,v retrieving revision 1.52 retrieving revision 1.52.2.1 diff -u -d -r1.52 -r1.52.2.1 --- CPersistentObject.vb 17 Dec 2004 03:29:01 -0000 1.52 +++ CPersistentObject.vb 10 Feb 2005 22:42:13 -0000 1.52.2.1 @@ -1224,7 +1224,12 @@ ''' </history> '''----------------------------------------------------------------------------- Public Overridable Function Copy() As IPersistableObject Implements IPersistentObject.Copy - Return Me.MemberwiseClone + Dim obj As CPersistentObject + obj = CType(Me.MemberwiseClone, CPersistentObject) + 'Because memberwise clone only reference copies collections we should also + 'copy the collections as well, since failing to do so can corrupt the cache. + CPersistenceBroker.CopyCollections(Me, obj) + Return obj End Function '''----------------------------------------------------------------------------- |
From: Richard B. <rb...@us...> - 2005-02-10 04:23:58
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv837/InheritedClasses Modified Files: ManyToManyTests_v2.vb Log Message: Unit test for many-to-many deletion Index: ManyToManyTests_v2.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/ManyToManyTests_v2.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ManyToManyTests_v2.vb 9 Feb 2005 06:20:50 -0000 1.1 +++ ManyToManyTests_v2.vb 10 Feb 2005 04:23:48 -0000 1.2 @@ -74,5 +74,72 @@ Assert.AreEqual(2, B.M2MACollection.Count) End Sub + <Test()> Public Sub SaveThenDelete() + Dim gval As String + Dim x As Integer, y As Integer + A = New M2MA + A.Description = "A1" + gval = A.GUIDValue + B = New M2MB + B.Description = "B1" + A.M2MBCollection.Add(B) + B.M2MACollection.Add(A) + Dim B2 As M2MB = New M2MB + B2.Description = "B2" + A.M2MBCollection.Add(B2) + Dim A2 As M2MA = New M2MA + A2.Description = "A2" + B2.M2MACollection.Add(A2) + A.Save() + pbroker.ClearCache() + A = New M2MA + A.GUIDValue = gval + A.Retrieve() + Assert.AreEqual(2, A.M2MBCollection.Count) + 'Order of guids can affect order of the collection + If A.M2MBCollection.Item(0).M2MACollection.Count = 1 Then + x = 0 + y = 1 + Else + x = 1 + y = 0 + End If + B = A.M2MBCollection.Item(x) + Assert.IsNotNull(B) + Assert.AreEqual("B1", B.Description) + Assert.AreEqual(1, B.M2MACollection.Count) + Assert.IsTrue(A.Equals(B.M2MACollection.Item(0))) + B = A.M2MBCollection.Item(y) + Assert.IsNotNull(B) + Assert.AreEqual("B2", B.Description) + Assert.AreEqual(2, B.M2MACollection.Count) + 'Now delete B2 - because of autodelete, allobjects should be delete + B.Delete() + A = New M2MA + A.GUIDValue = gval + A.Retrieve() + Assert.IsFalse(A.Persistent) + End Sub + + <Test()> Public Sub SaveThenChangeKeyValues() + Dim gvalA, gvalB As String + Dim s As String + A = New M2MA + A.Description = "A1" + gvalA = A.GUIDValue + B = New M2MB + B.Description = "B1" + gvalB = B.GUIDValue + A.M2MBCollection.Add(B) + B.M2MACollection.Add(A) + A.Save() + A.GUIDValue = Guid.NewGuid.ToString("N") + A.SetDirtyFlag() + A.Save() + s = "select * from ManyToManyAB where AGuidValue = """ & gvalA & """ and BGuidValue = """ & gvalB & """" + Dim c As CCursor = pbroker.ProcessPureSQL(s, A.getClassMap.RelationalDatabase.getConnection(Nothing)) + Assert.AreEqual(0, c.ResultSet.ResultSet.Tables(0).Rows.Count) + End Sub + End Class End Namespace \ No newline at end of file |
From: Richard B. <rb...@us...> - 2005-02-10 04:22:57
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv373 Modified Files: CAssociationObject.vb CCacheEntry.vb CPersistenceBroker.vb CXMLConfigLoader.vb Log Message: Changes for delete handling in many-to-many associations Index: CAssociationObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CAssociationObject.vb,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- CAssociationObject.vb 9 Feb 2005 06:24:45 -0000 1.1 +++ CAssociationObject.vb 10 Feb 2005 04:22:39 -0000 1.2 @@ -4,10 +4,9 @@ Private m_objA As IPersistableObject Private m_objB As IPersistableObject Private m_classMapA As CClassMap - Private m_classMapB As CClassMap Private m_association As CUDAMap - Private m_objACol As Collection - Private m_objBCol As Collection + Private m_objACol As New Collection + Private m_objBCol As New Collection Private m_deleteNeeded As Boolean Public Property ObjectA() As IPersistableObject @@ -16,21 +15,13 @@ End Get Set(ByVal Value As IPersistableObject) m_objA = Value + m_classMapA = m_objA.GetClassMap If Not m_objB Is Nothing AndAlso Not m_objA Is Nothing Then - checkifdeletewillbeneeded() + CheckIfDeleteWillBeNeeded() End If End Set End Property - Public Property ClassMapA() As CClassMap - Get - Return m_classMapA - End Get - Set(ByVal Value As CClassMap) - m_classMapA = Value - End Set - End Property - Public Property ObjectB() As IPersistableObject Get Return m_objB @@ -38,20 +29,11 @@ Set(ByVal Value As IPersistableObject) m_objB = Value If Not m_objA Is Nothing AndAlso Not m_objB Is Nothing Then - checkifdeletewillbeneeded() + CheckIfDeleteWillBeNeeded() End If End Set End Property - Public Property ClassMapB() As CClassMap - Get - Return m_classMapB - End Get - Set(ByVal Value As CClassMap) - m_classMapB = Value - End Set - End Property - Public Property Association() As CUDAMap Get Return m_association @@ -78,6 +60,9 @@ Dim fromObj, toObj As IPersistableObject Dim i As Short + If m_classMapA Is Nothing Then + Throw New AToMSFramework.NoClassMapException("No class map for " & m_objA.GetObjectType.Name) + End If db = m_classMapA.RelationalDatabase 'Determine which order classes are in @@ -150,6 +135,9 @@ Dim fromObj, toObj As IPersistableObject Dim i As Short + If m_classMapA Is Nothing Then + Throw New AToMSFramework.NoClassMapException("No class map for " & m_objA.GetObjectType.Name) + End If db = m_classMapA.RelationalDatabase 'Determine which order classes are in @@ -164,28 +152,31 @@ m_deleteStatement.addSqlClause(m_association.AssocationTable.Name & " ") m_deleteStatement.addSqlClause(db.getClauseStringWhere & " ") paramCount = 1 + isFirst = True For i = 0 To m_association.AssocationTable.FromKeys.Count - 1 Key = m_association.AssocationTable.FromKeys.Item(i) - If i > 1 Then + If Not isFirst Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If - m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) + isFirst = False + m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) m_deleteStatement.addSqlParameter(paramCount, fromObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i For i = 0 To m_association.AssocationTable.ToKeys.Count - 1 Key = m_association.AssocationTable.ToKeys.Item(i) - If i > 1 Then + If Not isFirst Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If - m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) - m_deleteStatement.addSqlParameter(paramCount, fromObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) + isFirst = False + m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) + m_deleteStatement.addSqlParameter(paramCount, toObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i Dim x As String = m_deleteStatement.SqlString Dim p As CSQLParameter - For i = 1 To paramCount + For i = 1 To paramCount - 1 p = m_deleteStatement.Parameters.Item(i) If IsNullAlias(p.Value) Then If db.UseANSINulls = True Then @@ -213,6 +204,9 @@ Dim fromCol, toCol As Collection Dim i As Short + If m_classMapA Is Nothing Then + Throw New AToMSFramework.NoClassMapException("No class map for " & m_objA.GetObjectType.Name) + End If db = m_classMapA.RelationalDatabase 'Determine which order classes are in @@ -231,28 +225,31 @@ m_deleteStatement.addSqlClause(m_association.AssocationTable.Name & " ") m_deleteStatement.addSqlClause(db.getClauseStringWhere & " ") paramCount = 1 + isFirst = True For i = 0 To m_association.AssocationTable.FromKeys.Count - 1 Key = m_association.AssocationTable.FromKeys.Item(i) - If i > 1 Then + If Not isFirst Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If - m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) - m_deleteStatement.addSqlParameter(paramCount, fromCol.Item(i), Key.ColumnMap) + isFirst = False + m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) + m_deleteStatement.addSqlParameter(paramCount, fromCol.Item(i + 1), Key.ColumnMap) paramCount += 1 Next i For i = 0 To m_association.AssocationTable.ToKeys.Count - 1 Key = m_association.AssocationTable.ToKeys.Item(i) - If i > 1 Then + If Not isFirst Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If - m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) - m_deleteStatement.addSqlParameter(paramCount, toCol.Item(i), Key.ColumnMap) + isFirst = False + m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & paramCount.ToString & "_")) + m_deleteStatement.addSqlParameter(paramCount, toCol.Item(i + 1), Key.ColumnMap) paramCount += 1 Next i Dim x As String = m_deleteStatement.SqlString Dim p As CSQLParameter - For i = 1 To paramCount + For i = 1 To paramCount - 1 p = m_deleteStatement.Parameters.Item(i) If IsNullAlias(p.Value) Then If db.UseANSINulls = True Then Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.92 retrieving revision 1.93 diff -u -d -r1.92 -r1.93 --- CPersistenceBroker.vb 9 Feb 2005 06:24:44 -0000 1.92 +++ CPersistenceBroker.vb 10 Feb 2005 04:22:39 -0000 1.93 @@ -302,6 +302,9 @@ tmpObj = m_cache.Item(obj) End If End If + If tmpObj Is Nothing AndAlso m_cache.Status = CCacheCollection.StatusEnum.Deleted Then + Return False + End If If Not tmpObj Is Nothing Then t = tmpObj.GetObjectType If t Is obj.GetObjectType Or t.IsSubclassOf(obj.GetObjectType) Then @@ -863,7 +866,7 @@ Dim inTicks As Long, outTicks As Long inTicks = Now.Ticks - Dim cm As CClassMap = obj.ClassMapA + Dim cm As CClassMap = obj.ObjectA.GetClassMap Dim conn As _CConnection = cm.RelationalDatabase.getConnection(Nothing) Try conn.startTransaction() @@ -1107,71 +1110,36 @@ '''----------------------------------------------------------------------------- Private Sub deletePrivateObject(ByRef obj As IPersistableObject, ByVal conn As _CConnection, ByVal deleteSuperClass As Boolean) Dim clMap As CClassMap - clMap = obj.GetClassMap Dim cm As CClassMap - cm = clMap - - Debug.WriteLine("Deleting object " & cm.Name) - - 'process associations and delete if deleteAutomatic Dim udaMap As CUDAMap Dim aCriteria As CRetrieveCriteria Dim cursor As CCursor Dim Value As IPersistableObject Dim ValueVar As String Dim col As IList + Dim assocObj As CAssociationObject Dim colCriteriaParameters As New Collection Dim i As Short, j As Short, k As Short + Dim statement As CSqlStatement + + clMap = obj.GetClassMap + cm = clMap + Debug.WriteLine("Deleting object " & cm.Name) Dim myKeys(cm.AssociationMaps.Count) As String cm.AssociationMaps.Keys.CopyTo(myKeys, 0) - Try PCDeletes.Increment() Catch End Try - - For i = 0 To cm.AssociationMaps.Count - 1 - udaMap = cm.AssociationMaps.Item(myKeys(i)) - If udaMap.DeleteAutomatic Then - For j = 1 To udaMap.getSize - If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - Value = obj.GetObjectByAttribute(udaMap.FromClassTarget) - If Not Value Is Nothing Then - If retrieveObject(Value, False, True) Then - 'If Value.Retrieve() Then - deletePrivateObject(Value, conn, deleteSuperClass) - End If - End If - ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.GetCollectionByAttribute(udaMap.FromClassTarget) - If Not col Is Nothing Then - For k = 0 To col.Count - 1 - If col.Item(k).GetType.IsSubclassOf(GetType(CPersistentObject)) Then - Value = col.Item(k) - Else - Value = Me.getInjectedObject(col.Item(k)) - End If - If retrieveObject(Value, False, True) Then - 'If Value.Retrieve Then - deletePrivateObject(Value, conn, deleteSuperClass) - End If - Next k - col = Nothing - End If - End If - Next j - End If - Next i - - Dim statement As CSqlStatement + 'We need to first delete the current object and then process associations + 'so that circular object references do not cause an infinite loop statement = clMap.getDeleteSqlFor(obj) Try PCSQLHits.Increment() Catch End Try conn.processStatement(statement) - If deleteSuperClass Then cm = cm.SuperClass If Not cm Is Nothing Then @@ -1192,6 +1160,85 @@ Catch End Try End If + + For i = 0 To cm.AssociationMaps.Count - 1 + udaMap = cm.AssociationMaps.Item(myKeys(i)) + If udaMap.DeleteAutomatic Then + If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then + Value = obj.GetObjectByAttribute(udaMap.FromClassTarget) + If Not Value Is Nothing Then + If retrieveObject(Value, False, True) Then + 'If Value.Retrieve() Then + deletePrivateObject(Value, conn, deleteSuperClass) + End If + End If + ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Or udaMap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY Then + If udaMap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY AndAlso obj.GetClassMap.Name = udaMap.ToClass.Name Then + col = obj.GetCollectionByAttribute(udaMap.ToClassTarget) + Else + col = obj.GetCollectionByAttribute(udaMap.FromClassTarget) + End If + If Not col Is Nothing Then + For k = 0 To col.Count - 1 + If col.Item(k).GetType.IsSubclassOf(GetType(CPersistentObject)) Then + Value = col.Item(k) + Else + Value = Me.getInjectedObject(col.Item(k)) + End If + If retrieveObject(Value, False, True) Then + deletePrivateObject(Value, conn, deleteSuperClass) + If udaMap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY Then + 'need to delete the associationtable entry as well + assocObj = New CAssociationObject + assocObj.ObjectA = obj + assocObj.ObjectB = Value + assocObj.Association = udaMap + statement = assocObj.getDeleteSql() + Try + PCSQLHits.Increment() + Catch + End Try + Try + 'If associationtable record was deleted by other object this will fail + conn.processStatement(statement) + Catch + End Try + End If + End If + Next k + col = Nothing + End If + End If + End If + Next i + + 'statement = clMap.getDeleteSqlFor(obj) + 'Try + ' PCSQLHits.Increment() + 'Catch + 'End Try + 'conn.processStatement(statement) + + 'If deleteSuperClass Then + ' cm = cm.SuperClass + ' If Not cm Is Nothing Then + ' 'delete super class and its associations + ' Value = obj.GetObjectByClassMap(cm) + ' If retrieveObject(Value, False, True) Then + ' 'If Value.Retrieve() Then + ' deletePrivateObject(Value, conn, True) + ' End If + ' End If + 'End If + + 'obj.Persistent = False + 'If m_useCache Then + ' m_cache.Remove(obj) 'remove from the cache + ' Try + ' PCCacheSize.RawValue = m_cache.Count + ' Catch + ' End Try + 'End If colCriteriaParameters = Nothing End Sub @@ -1899,6 +1946,28 @@ End Function + Public Function ProcessPureSQL(ByVal inSQL As String, ByVal conn As _CConnection) As CCursor + Dim statement As New CSqlStatement + statement.SqlString = inSQL + + Try + PCSQLHits.Increment() + Catch + End Try + + Dim cursor As CCursor + Dim rs As CResultset + rs = conn.processSelectStatement(statement) + + cursor = New CCursor + cursor.ParentCriteria = Nothing + cursor.ResultSet = rs + cursor.ClassMap = Nothing + cursor.HoldsProxies = False + Return cursor + End Function + + '''----------------------------------------------------------------------------- ''' <summary> ''' Initiates a transaction on all database connections. @@ -2577,8 +2646,6 @@ aObj = New CAssociationObject aObj.ObjectA = obj aObj.ObjectB = value - aObj.ClassMapA = obj.GetClassMap - aObj.ClassMapB = value.GetClassMap aObj.Association = udamap queue.Enqueue(aObj) End If Index: CCacheEntry.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCacheEntry.vb,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- CCacheEntry.vb 6 Feb 2005 02:44:00 -0000 1.27 +++ CCacheEntry.vb 10 Feb 2005 04:22:39 -0000 1.28 @@ -174,7 +174,6 @@ 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 @@ -572,6 +571,13 @@ Private m_expiryInterval As Double Private m_objectsLoading As Boolean + Public Enum StatusEnum + Found + NotFound + Deleted + End Enum + Private m_status As StatusEnum + '''----------------------------------------------------------------------------- ''' <summary> ''' Adds a persistent object to the cache. @@ -698,15 +704,18 @@ If found Then 'Debug.WriteLine("Cache - Found object in cache") If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted Then + m_status = StatusEnum.Deleted Return Nothing End If Debug.WriteLine([String].Format("Cache - getting {0} object from cache. Key..." & vbCrLf & x.Key.ToString, x.Key.ObjType.Name)) + m_status = StatusEnum.Found Return GetCachedObject(ce) End If End If End If End While 'Debug.WriteLine("Cache - object not cached") + m_status = StatusEnum.NotFound Return Nothing End Function @@ -728,16 +737,22 @@ Get Dim ce As CCacheEntry ce = MyBase.Item(OIDValue) - If ce Is Nothing Then Return Nothing + If ce Is Nothing Then + m_status = StatusEnum.NotFound + Return Nothing + End If If ce.IsExpired() And Not ce.PersistentObject.IsDirty Then 'Debug.WriteLine("Cache - removing expired object: " & OIDValue) - MyBase.Remove(Item) 'delete object from cache + MyBase.Remove(Item) 'delete object from cache + m_status = StatusEnum.NotFound Return Nothing End If 'Debug.WriteLine("Cache - returning copy of object from cache" & OIDValue) If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted Then + m_status = StatusEnum.Deleted Return Nothing End If + m_status = StatusEnum.Found Return GetCachedObject(ce) End Get End Property @@ -763,19 +778,26 @@ Dim ckey As CCacheKey ckey = New CCacheKey(obj) If Not ckey.hasLegitValues Then + m_status = StatusEnum.NotFound Return Nothing End If ce = MyBase.Item(ckey) - If ce Is Nothing Then Return Nothing + If ce Is Nothing Then + m_status = StatusEnum.NotFound + Return Nothing + End If If ce.IsExpired() And Not ce.PersistentObject.IsDirty Then 'Debug.WriteLine([String].Format("Cache - removing expired {0} object. Key... " & vbCrLf & ckey.ToString, ckey.ObjType.Name)) - MyBase.Remove(ckey) 'delete object from cache + MyBase.Remove(ckey) 'delete object from cache + m_status = StatusEnum.NotFound Return Nothing End If If ce.TransactionType = CCacheEntry.CacheTransaction.Deleted Then + m_status = StatusEnum.Deleted Return Nothing End If Debug.WriteLine([String].Format("Cache - getting {0} object from cache. Key..." & vbCrLf & ckey.ToString, ckey.ObjType.Name)) + m_status = StatusEnum.Found Return GetCachedObject(ce) End Get End Property @@ -989,4 +1011,10 @@ Return outString End Function + + Public ReadOnly Property Status() As StatusEnum + Get + Return m_status + End Get + End Property End Class \ No newline at end of file Index: CXMLConfigLoader.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CXMLConfigLoader.vb,v retrieving revision 1.31 retrieving revision 1.32 diff -u -d -r1.31 -r1.32 --- CXMLConfigLoader.vb 9 Feb 2005 06:24:45 -0000 1.31 +++ CXMLConfigLoader.vb 10 Feb 2005 04:22:46 -0000 1.32 @@ -716,6 +716,9 @@ .ProviderType = assocKey.AttributeMap.ColumnMap.ProviderType .StorageSize = assocKey.AttributeMap.ColumnMap.StorageSize .StorageType = assocKey.AttributeMap.ColumnMap.StorageType + .TableMap = New CTableMap + .TableMap.Name = assocTable.Name + .TableMap.TableOwner = assocTable.TableOwner End With assocTable.ToKeys.Add(assocKey) End If |
From: Richard B. <rb...@us...> - 2005-02-09 06:24:55
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29948 Modified Files: AToMSFramework.vbproj CClassMap.vb CCriteriaCondition.vb CInjectedObject.vb CJoin.vb CMultiSummaryCriteria.vb CPersistenceBroker.vb CPersistentObject.vb CSelectInCriteria.vb CUDAMap.vb CXMLConfigLoader.vb XMLMapping.xsd Added Files: CAssociationKey.vb CAssociationObject.vb CAssociationTable.vb Log Message: -- INCOMPLETE -- New code to allow associations to be declared as Many-To-Many without needing a class just to manage the association. Save and Retrieve works, haven't tested deletes or retrieve criteria yet Index: AToMSFramework.vbproj =================================================================== RCS file: /cvsroot/jcframework/dotnet/AToMSFramework.vbproj,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- AToMSFramework.vbproj 7 Feb 2005 07:37:33 -0000 1.22 +++ AToMSFramework.vbproj 9 Feb 2005 06:24:44 -0000 1.23 @@ -109,6 +109,21 @@ BuildAction = "None" /> <File + RelPath = "CAssociationKey.vb" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "CAssociationObject.vb" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "CAssociationTable.vb" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "CAttributeMap.vb" SubType = "Code" BuildAction = "Compile" Index: CPersistenceBroker.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CPersistenceBroker.vb,v retrieving revision 1.91 retrieving revision 1.92 diff -u -d -r1.91 -r1.92 --- CPersistenceBroker.vb 7 Feb 2005 07:37:34 -0000 1.91 +++ CPersistenceBroker.vb 9 Feb 2005 06:24:44 -0000 1.92 @@ -287,6 +287,7 @@ Dim i As Integer Dim isfirst As Boolean = True Dim am As CAttributeMap + Dim fromClass, toClass As CClassMap cm = obj.GetClassMap @@ -406,11 +407,11 @@ If udamap.RetrieveAutomatic Then mapName = "t" & classMapCount.ToString classMapCount += 1 - cm2 = udamap.ForClass + cm2 = udamap.ToClass 'Only process one-to-one relationships on the first record retrieved If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE And i = 0 Then gotValue = False - targetobj = obj.GetObjectByAttribute(udamap.Target) + targetobj = obj.GetObjectByAttribute(udamap.FromClassTarget) If Not targetobj Is Nothing Then 'if the class as child classes then check if the targetobj is of type child If cm2.ChildrenMaps.Count > 0 Then @@ -435,7 +436,7 @@ Catch End Try End If - obj.SetAttributeValue(udamap.Target, targetobj.GetSourceObject) + obj.SetAttributeValue(udamap.FromClassTarget, targetobj.GetSourceObject) If Not targetobj.AssociationsLoaded Then If udamap.LazyLoad Then targetobj.IsDirty = False @@ -453,10 +454,10 @@ End If If Not gotValue Then 'Check whether the object is of child type - If udamap.ForClass.ChildrenMaps.Count > 0 Then - targetobj = Me.createTargetObjectForMultipleInheritance(udamap.ForClass, obj.GetObjectType, obj.GetObjectType.Namespace, rs.ResultSet.Tables(0).Rows(i), joins, conn) + If udamap.ToClass.ChildrenMaps.Count > 0 Then + targetobj = Me.createTargetObjectForMultipleInheritance(udamap.ToClass, obj.GetObjectType, obj.GetObjectType.Namespace, rs.ResultSet.Tables(0).Rows(i), joins, conn) 'update classMapCount with the child count number - classMapCount += Me.getChildCountForMultipleInheritance(udamap.ForClass) + classMapCount += Me.getChildCountForMultipleInheritance(udamap.ToClass) classMapCount -= 1 'This is because we added one in the beginning of the for loop If Not targetobj Is Nothing AndAlso targetobj.Persistent Then @@ -487,12 +488,12 @@ targetobj.IsDirty = False targetobj.OriginalCacheKey = New CCacheKey(targetobj) End If - obj.SetAttributeValue(udamap.Target, targetobj.GetSourceObject) + obj.SetAttributeValue(udamap.FromClassTarget, targetobj.GetSourceObject) End If Else 'Object doesn't exist - let's create it 'See if the assembly path is specified - targetobj = udamap.ForClass.CreateObjectInstance + targetobj = udamap.ToClass.CreateObjectInstance If Not targetobj Is Nothing Then cm2.populateObject(cm2, targetobj, rs, mapName) @@ -524,19 +525,33 @@ targetobj.IsDirty = False targetobj.OriginalCacheKey = New CCacheKey(targetobj) End If - obj.SetAttributeValue(udamap.Target, targetobj.GetSourceObject) + obj.SetAttributeValue(udamap.FromClassTarget, targetobj.GetSourceObject) End If End If End If End If - ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.GetCollectionByAttribute(udamap.Target) + ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Or udamap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY Then + If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then + col = obj.GetCollectionByAttribute(udamap.FromClassTarget) + fromClass = udamap.FromClass + toClass = udamap.ToClass + Else + If obj.GetClassMap.Name = udamap.FromClass.Name Then + col = obj.GetCollectionByAttribute(udamap.FromClassTarget) + fromClass = udamap.FromClass + toClass = udamap.ToClass + Else + col = obj.GetCollectionByAttribute(udamap.ToClassTarget) + toClass = udamap.FromClass + fromClass = udamap.ToClass + End If + End If 'Check whether the object is of child type - If udamap.ForClass.ChildrenMaps.Count > 0 Then - targetobj = Me.createTargetObjectForMultipleInheritance(udamap.ForClass, obj.GetObjectType, obj.GetObjectType.Namespace, rs.ResultSet.Tables(0).Rows(i), joins, conn) + If fromClass.ChildrenMaps.Count > 0 Then + targetobj = Me.createTargetObjectForMultipleInheritance(toClass, obj.GetObjectType, obj.GetObjectType.Namespace, rs.ResultSet.Tables(0).Rows(i), joins, conn) 'update classMapCount with the child count number - classMapCount += Me.getChildCountForMultipleInheritance(udamap.ForClass) + classMapCount += Me.getChildCountForMultipleInheritance(toClass) classMapCount -= 1 'This is because we added one in the beginning of the for loop If Not targetobj Is Nothing AndAlso targetobj.Persistent Then tmpObj = m_cache.Item(targetobj) @@ -588,8 +603,7 @@ End If End If Else - targetobj = udamap.ForClass.CreateObjectInstance - + targetobj = toClass.CreateObjectInstance rw = rs.ResultSet.Tables(0).Rows(i) cm2.populateObject(cm2, targetobj, rw, mapName) If targetobj.Persistent Then @@ -701,9 +715,9 @@ udaMap = cm.AssociationMaps.Item(myKeys(i)) If udaMap.RetrieveAutomatic Then aCriteria = New CRetrieveCriteria - aCriteria.ClassMap = udaMap.ForClass + aCriteria.ClassMap = udaMap.ToClass If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - Value = obj.GetObjectByAttribute(udaMap.Target) + Value = obj.GetObjectByAttribute(udaMap.FromClassTarget) gotValue = False If Not Value Is Nothing Then 'Need to know if returned object is persistent and has a legitimate key @@ -717,14 +731,14 @@ Value = anObjPers Value.IsDirty = False Value.OriginalCacheKey = New CCacheKey(Value) - obj.SetAttributeValue(udaMap.Target, Value.GetSourceObject) + obj.SetAttributeValue(udaMap.FromClassTarget, Value.GetSourceObject) gotValue = True End If End If End If If Not gotValue Then 'Object doesn't exist - let's create it - Value = udaMap.ForClass.CreateObjectInstance + Value = udaMap.ToClass.CreateObjectInstance If Not Value Is Nothing Then 'Loop through fields in the association For j = 1 To udaMap.getSize @@ -745,12 +759,12 @@ End Try End If If found Then - Value.IsDirty = False 'After populating a new object - Value.OriginalCacheKey = New CCacheKey(Value) - obj.SetAttributeValue(udaMap.Target, Value.GetSourceObject) + Value.IsDirty = False 'After populating a new object + Value.OriginalCacheKey = New CCacheKey(Value) + obj.SetAttributeValue(udaMap.FromClassTarget, Value.GetSourceObject) + End If End If End If - End If ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then For j = 1 To udaMap.getSize ValueVar = cm.getValueForRelationalDatabase(obj.GetValueByAttribute(udaMap.getEntry(j).FromAttrMap.Name)) @@ -758,23 +772,23 @@ Next j aCriteria.ReturnFullObjects = Not udaMap.LazyLoad cursor = processCriteria(aCriteria, colCriteriaParameters, conn) - col = obj.GetCollectionByAttribute(udaMap.Target) + col = obj.GetCollectionByAttribute(udaMap.FromClassTarget) If col Is Nothing Then - Throw New RetrieveException("Collection " & udaMap.Target & " is not initialised for " & obj.GetObjectType.ToString) + Throw New RetrieveException("Collection " & udaMap.FromClassTarget & " is not initialised for " & obj.GetObjectType.ToString) End If col.Clear() 'Clear the collection before polpulating, just to be sure While cursor.hasElements And Not cursor.EOF - Value = udaMap.ForClass.CreateObjectInstance + Value = udaMap.ToClass.CreateObjectInstance anObjPers = Value If udaMap.LazyLoad Then cursor.loadProxy(anObjPers.GetSourceObject) Else - cursor.loadObject(anObjPers.GetSourceObject) - 'To prevent recursive associations causing problems we need to add the - 'object to the cache here as a preliminary measure - m_cache.Add(anObjPers) - retrieveAssociations(anObjPers, conn, anObjPers.GetClassMap, useCache) + cursor.loadObject(anObjPers.GetSourceObject) + 'To prevent recursive associations causing problems we need to add the + 'object to the cache here as a preliminary measure + m_cache.Add(anObjPers) + retrieveAssociations(anObjPers, conn, anObjPers.GetClassMap, useCache) End If anObjPers.IsDirty = False 'After populating a new object anObjPers.OriginalCacheKey = New CCacheKey(anObjPers) @@ -844,6 +858,33 @@ End SyncLock End Sub + Friend Sub saveAssociationObject(ByRef obj As CAssociationObject) + SyncLock GetType(CPersistenceBroker) + Dim inTicks As Long, outTicks As Long + inTicks = Now.Ticks + + Dim cm As CClassMap = obj.ClassMapA + Dim conn As _CConnection = cm.RelationalDatabase.getConnection(Nothing) + Try + conn.startTransaction() + conn.AutoCommit = False + savePrivateAssociationObject(obj, conn) + conn.commit() + Catch ex As Exception + conn.rollback() + cm.RelationalDatabase.freeConnection(conn) + Throw New SaveException(ex.Message, ex) + End Try + cm.RelationalDatabase.freeConnection(conn) + outTicks = Now.Ticks + Try + PCAverageTime.RawValue = outTicks - inTicks + PCAverageTimeBase.Increment() + Catch + End Try + End SyncLock + End Sub + '''----------------------------------------------------------------------------- ''' <summary> ''' Method to actually save (persist) an object. @@ -933,6 +974,39 @@ End If End Sub + Private Sub savePrivateAssociationObject(ByRef obj As CAssociationObject, ByVal conn As _CConnection) + Dim statement As CSqlStatement + Dim i As Integer + Dim objACol As Collection + Dim objBCol As Collection + Dim doDelete As Boolean + Dim attrMap As CAttributeMap + Dim Value, Value2 As Object + + Debug.WriteLine("Saving many-to-many association object " & obj.Association.AssocationTable.Name) + + If obj.DeleteNeeded Then + Try + statement = obj.getDeleteSqlUsingOriginalValues() + conn.processStatement(statement) + Catch + End Try + End If + + Try + statement = obj.getInsertSql + conn.processStatement(statement) + Catch ex As Exception + End Try + + Try + PCSQLHits.Increment() + PCInserts.Increment() + Catch + End Try + End Sub + + '''----------------------------------------------------------------------------- ''' <summary> ''' Deletes an object from the database. Does not delete the parent object(s). @@ -973,7 +1047,7 @@ Try deletePrivateObject(obj, conn, deleteSuperClass) conn.commit() - Catch ex As Exception + Catch ex As Exception x = New DeleteException(ex.Message, ex) conn.rollback() Finally @@ -988,7 +1062,7 @@ If Not x Is Nothing Then Throw x End If - End Try + End Try End SyncLock End Sub @@ -1062,7 +1136,7 @@ If udaMap.DeleteAutomatic Then For j = 1 To udaMap.getSize If udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - Value = obj.GetObjectByAttribute(udaMap.Target) + Value = obj.GetObjectByAttribute(udaMap.FromClassTarget) If Not Value Is Nothing Then If retrieveObject(Value, False, True) Then 'If Value.Retrieve() Then @@ -1070,7 +1144,7 @@ End If End If ElseIf udaMap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.GetCollectionByAttribute(udaMap.Target) + col = obj.GetCollectionByAttribute(udaMap.FromClassTarget) If Not col Is Nothing Then For k = 0 To col.Count - 1 If col.Item(k).GetType.IsSubclassOf(GetType(CPersistentObject)) Then @@ -1819,9 +1893,9 @@ Return cursor Catch - firstClassMap.RelationalDatabase.freeConnection(conn) - Return Nothing - End Try + firstClassMap.RelationalDatabase.freeConnection(conn) + Return Nothing + End Try End Function @@ -2191,8 +2265,8 @@ fromClassMap = m_classMaps.Item(types(i).Name) toClassMap = m_classMaps.Item(afAssociation.TargetClass.Name) udaAm = New CUDAMap - udaAm.ForClass = toClassMap - udaAm.Target = afAssociation.TargetProperty + udaAm.ToClass = toClassMap + udaAm.FromClassTarget = afAssociation.TargetProperty udaAm.DeleteAutomatic = afAssociation.Delete udaAm.SaveAutomatic = afAssociation.Save udaAm.RetrieveAutomatic = afAssociation.Retrieve @@ -2201,11 +2275,10 @@ udaAm.RetrieveAutomatic = True End If If afAssociation.Name Is Nothing OrElse afAssociation.Name = [String].Empty Then - udaAm.Name = udaAm.Target + udaAm.Name = udaAm.FromClassTarget Else udaAm.Name = afAssociation.Name End If - udaAm.Inverse = False udaAm.Cardinality = afAssociation.Cardinality att = types(i).GetCustomAttributes(GetType(AFAssociationEntryAttribute), False) If att.Length > 0 Then @@ -2387,11 +2460,13 @@ Dim de As DictionaryEntry Dim udamap As CUDAMap Dim value, o As IPersistableObject + Dim qObj As Object Dim col As IList 'Dim stack As New Stack Dim queue As New Queue Dim i, k As Integer Dim tmpObj As Object + Dim aObj As CAssociationObject If obj.IsQueued Then 'if an object has already been added to the save queue, there is no need to add @@ -2414,9 +2489,6 @@ If Not obj.IsDirty Then Return queue 'Do not save if nothing changed End If If obj.IsProxy Then Return queue 'Do not save if object is proxied - 'If obj.GetObjectType.IsSubclassOf(GetType(CPersistentObject)) Then - ' If Not CType(obj, CPersistentObject).IsValid Then Return queue 'Do not save if object is not valid - 'End If If GetType(IValidation).IsInstanceOfType(obj.GetSourceObject) Then If Not CType(obj.GetSourceObject, IValidation).IsValid Then Return queue 'Do not save if object is not valid End If @@ -2427,7 +2499,6 @@ Return queue End If If includeBaseObject Then - 'obj.IsDirty = False 'Added to queue so clear dirty flag queue.Enqueue(obj) End If Else @@ -2459,14 +2530,14 @@ udamap = cm.getStraightAssociationMap(i) If udamap.SaveAutomatic Then If udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE Then - value = obj.GetObjectByAttribute(udamap.Target) + value = obj.GetObjectByAttribute(udamap.FromClassTarget) If Not value Is Nothing Then For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) queue.Enqueue(o) Next End If ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.GetCollectionByAttribute(udamap.Target) + col = obj.GetCollectionByAttribute(udamap.FromClassTarget) If Not col Is Nothing Then For k = 0 To col.Count() - 1 tmpObj = col.Item(k) @@ -2480,22 +2551,14 @@ Next Next k End If - End If - End If - Next i - - For i = 1 To cm.getInverseAssociationMapSize - 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 + ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY Then + If obj.GetClassMap.Name = udamap.FromClass.Name Then + col = obj.GetCollectionByAttribute(udamap.FromClassTarget) + Else + If Not udamap.ToClassTarget Is Nothing Then + col = obj.GetCollectionByAttribute(udamap.ToClassTarget) + End If End If - ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - col = obj.GetCollectionByAttribute(udamap.Target) If Not col Is Nothing Then For k = 0 To col.Count() - 1 tmpObj = col.Item(k) @@ -2504,8 +2567,21 @@ Else value = tmpObj End If - For Each o In getObjectsToSave(value, True, checkAssociationsRecursivly) - queue.Enqueue(o) + aObj = Nothing + For Each qObj In getObjectsToSave(value, True, checkAssociationsRecursivly) + queue.Enqueue(qObj) + If aObj Is Nothing AndAlso value.Equals(qObj) Then + 'since we are saving this object (obj) and one of the objects in the association + 'we need to ensure the association table gets updated. This will be done via + 'the CAssociationObject class. We need to create an object here for the class. + aObj = New CAssociationObject + aObj.ObjectA = obj + aObj.ObjectB = value + aObj.ClassMapA = obj.GetClassMap + aObj.ClassMapB = value.GetClassMap + aObj.Association = udamap + queue.Enqueue(aObj) + End If Next Next k End If @@ -2939,7 +3015,7 @@ PCAverageTimeBase.RawValue = 0 Catch ex As Exception Trace.WriteLine("Could not create performance counters. If using ASP.NET please see http://objectsharp.com/Blogs/bruce/archive/2003/12/05/222.aspx" & _ - vbCrLf & ex.Message) + vbCrLf & ex.Message) End Try End Sub End Class \ No newline at end of file Index: CXMLConfigLoader.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CXMLConfigLoader.vb,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- CXMLConfigLoader.vb 7 Feb 2005 07:37:35 -0000 1.30 +++ CXMLConfigLoader.vb 9 Feb 2005 06:24:45 -0000 1.31 @@ -137,12 +137,12 @@ '''----------------------------------------------------------------------------- Private Sub IConfigLoader_loadConfig(ByRef dbMap As HybridDictionary, ByRef clMap As HybridDictionary) Implements _IConfigLoader.loadConfig m_classMap = clMap - m_databaseMap = dbMap - 'Specifically clear database and class maps - dbMap.Clear() - clMap.Clear() + m_databaseMap = dbMap + 'Specifically clear database and class maps + dbMap.Clear() + clMap.Clear() - Dim doc As New XmlDocument + Dim doc As New XmlDocument Try doc.Load(Me.FileName) @@ -164,14 +164,14 @@ If node.NodeType = XmlNodeType.Element Then elem = node If node.Name = "database" Then - reldb = getRelationalDatabase(elem) - Try - dbMap.Add(reldb.Name, reldb) - Catch ex As Exception - Throw New AToMSFramework.XMLMappingException("Could not add database " & reldb.Name & vbCrLf & ex.Message, ex) - End Try - ElseIf node.Name = "class" Then - clm = getClassMap(elem) + reldb = getRelationalDatabase(elem) + Try + dbMap.Add(reldb.Name, reldb) + Catch ex As Exception + Throw New AToMSFramework.XMLMappingException("Could not add database " & reldb.Name & vbCrLf & ex.Message, ex) + End Try + ElseIf node.Name = "class" Then + clm = getClassMap(elem) If clm.ClassNameSpace <> String.Empty Then keyStr = clm.ClassNameSpace & "." & clm.Name Else @@ -182,10 +182,10 @@ Catch ex As Exception Throw New AToMSFramework.XMLMappingException("Could not add classmap " & clm.Name & vbCrLf & ex.Message, ex) End Try - ElseIf node.Name = "association" Then - processAssociation(elem) - End If - End If + ElseIf node.Name = "association" Then + processAssociation(elem) + End If + End If node = node.NextSibling() End While @@ -275,10 +275,10 @@ ''' </history> '''----------------------------------------------------------------------------- Private Function getClassMap(ByVal node As XmlElement) As CClassMap - Dim attrClassName As XmlAttribute, attrTable As XmlAttribute, attrTableOwner As XmlAttribute - Dim attrDatabase As XmlAttribute, attrSuperClassName As XmlAttribute, attrReadOnly As XmlAttribute, attrModifyOnly As XmlAttribute + Dim attrClassName As XmlAttribute, attrTable As XmlAttribute, attrTableOwner As XmlAttribute + Dim attrDatabase As XmlAttribute, attrSuperClassName As XmlAttribute, attrReadOnly As XmlAttribute, attrModifyOnly As XmlAttribute Dim attrClassNameSpace, attrAssemblyPath, attrSuperClassNameSpace As XmlAttribute - Dim attrSharedField As XmlAttribute, attrSharedValue As XmlAttribute + Dim attrSharedField As XmlAttribute, attrSharedValue As XmlAttribute Dim attrClassFactory As XmlAttribute attrClassName = node.GetAttributeNode("name") attrTable = node.GetAttributeNode("table") @@ -425,8 +425,8 @@ colMap.IsNullable = cc.Item(ClassMap.SharedTableField & "NL") Catch Throw New NoColumnException("Error retrieving storage information for column " _ - + ClassMap.SharedTableField + " in class " + ClassMap.Name _ - + ". Please check the shared table field in the mapping.") + + ClassMap.SharedTableField + " in class " + ClassMap.Name _ + + ". Please check the shared table field in the mapping.") End Try ClassMap.SharedTableColumnMap = colMap End If @@ -548,40 +548,47 @@ ''' </history> '''----------------------------------------------------------------------------- Private Sub processAssociation(ByVal node As XmlElement) - Dim attrToClass, attrFromClass, attrTarget As Object + Dim attrToClass, attrFromClass As XmlAttribute + Dim attrFromTarget, attrToTarget As XmlAttribute Dim attrCardinality As XmlAttribute + Dim attrName, attrOwner As XmlAttribute + Dim attrFromClassNameSpace As XmlAttribute + Dim attrToClassNameSpace As XmlAttribute + Dim attrFromAttribute As XmlAttribute + Dim attrToAttribute As XmlAttribute + Dim attrColumn As XmlAttribute Dim fromClassMap As CClassMap Dim toClassMap As CClassMap Dim udaAm As CUDAMap - Dim nodeChild As XmlNode - Dim elementChild As XmlElement + Dim nodeChild, nodeChild2 As XmlNode + Dim elementChild, elementChild2 As XmlElement Dim entry As CUDAMapEntry - Dim amFromAttribute As Object + Dim amFromAttribute As CAttributeMap Dim amToAttribute As CAttributeMap - Dim attrFromAttribute As Object - Dim attrToAttribute As XmlAttribute - Dim attrName As XmlAttribute - Dim attrFromClassNameSpace As XmlAttribute - Dim attrToClassNameSpace As XmlAttribute + Dim assocTable As CAssociationTable + Dim assocKey As CAssociationKey Dim keyStr As String Dim tmpStr As String attrFromClass = node.GetAttributeNode("fromClass") attrToClass = node.GetAttributeNode("toClass") - attrTarget = node.GetAttributeNode("target") + attrFromTarget = node.GetAttributeNode("target") + If attrFromTarget Is Nothing Then + attrFromTarget = node.GetAttributeNode("fromClassTarget") + End If + attrToTarget = node.GetAttributeNode("toClassTarget") attrCardinality = node.GetAttributeNode("cardinality") attrName = node.GetAttributeNode("name") attrFromClassNameSpace = node.GetAttributeNode("fromClassNameSpace") attrToClassNameSpace = node.GetAttributeNode("toClassNameSpace") - If ((Not attrFromClass Is Nothing) And (Not attrToClass Is Nothing) And (Not attrTarget Is Nothing)) Then + If ((Not attrFromClass Is Nothing) And (Not attrToClass Is Nothing) And (Not attrFromTarget Is Nothing)) Then If Not attrToClassNameSpace Is Nothing AndAlso Not attrFromClassNameSpace.Value Is Nothing Then keyStr = attrFromClassNameSpace.Value & "." & attrFromClass.Value Else keyStr = attrFromClass.Value End If fromClassMap = m_classMap.Item(keyStr) - 'fromClassMap = m_classMap.Item(attrFromClass.Value) If fromClassMap Is Nothing Then Throw New XMLMappingException("Error in association definition: fromClassMap = " + attrFromClass.Value) End If @@ -592,14 +599,16 @@ keyStr = attrToClass.Value End If toClassMap = m_classMap.Item(keyStr) - 'toClassMap = m_classMap.Item(attrToClass.Value) If toClassMap Is Nothing Then Throw New XMLMappingException("Error in association definition: toClassMap = " + attrToClass.Value) End If udaAm = New CUDAMap udaAm.FromClass = fromClassMap - udaAm.ForClass = toClassMap - udaAm.Target = attrTarget.Value + udaAm.toclass = toClassMap + udaAm.FromClassTarget = attrFromTarget.Value + If Not attrToTarget Is Nothing Then + udaAm.ToClassTarget = attrToTarget.Value + End If udaAm.DeleteAutomatic = node.GetAttributeNode("deleteAutomatic").Value udaAm.SaveAutomatic = node.GetAttributeNode("saveAutomatic").Value tmpStr = node.GetAttributeNode("retrieveAutomatic").Value @@ -612,18 +621,17 @@ udaAm.RetrieveAutomatic = False End If If attrName Is Nothing Then - udaAm.Name = udaAm.Target + udaAm.Name = udaAm.FromClassTarget Else udaAm.Name = attrName.Value End If - If Not node.GetAttribute("inverse") Is Nothing Then - udaAm.Inverse = node.GetAttributeNode("inverse").Value - End If If Not attrCardinality Is Nothing Then If UCase(attrCardinality.Value) = "ONETOONE" Then udaAm.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_ONE ElseIf UCase(attrCardinality.Value) = "ONETOMANY" Then udaAm.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY + ElseIf UCase(attrCardinality.Value) = "MANYTOMANY" Then + udaAm.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY End If End If @@ -631,6 +639,7 @@ Do While Not nodeChild Is Nothing If nodeChild.NodeType = XmlNodeType.Element Then elementChild = nodeChild + 'process association map entries If elementChild.Name = "entry" Then attrFromAttribute = elementChild.GetAttributeNode("fromAttribute") attrToAttribute = elementChild.GetAttributeNode("toAttribute") @@ -652,22 +661,81 @@ Throw New XMLMappingException("Error in association definition") End If entry = New CUDAMapEntry - If udaAm.Inverse Then - entry.FromAttrMap = amToAttribute - entry.ToAttrMap = amFromAttribute - Else - entry.FromAttrMap = amFromAttribute - entry.ToAttrMap = amToAttribute - End If + entry.FromAttrMap = amFromAttribute + entry.ToAttrMap = amToAttribute udaAm.addEntry(entry) End If + ElseIf elementChild.Name = "associationTable" Then + assocTable = New CAssociationTable + attrName = elementChild.GetAttributeNode("name") + attrOwner = elementChild.GetAttributeNode("owner") + If Not attrName Is Nothing Then + assocTable.Name = attrName.Value + If Not attrOwner Is Nothing Then + assocTable.TableOwner = attrOwner.Value + End If + nodeChild2 = elementChild.FirstChild + Do While Not nodeChild2 Is Nothing + If nodeChild2.NodeType = XmlNodeType.Element Then + elementChild2 = nodeChild2 + 'process association map entries + If elementChild2.Name = "fromClassKey" Then + attrName = elementChild2.GetAttributeNode("name") + attrColumn = elementChild2.GetAttributeNode("column") + If Not attrName Is Nothing And Not attrColumn Is Nothing Then + assocKey = New CAssociationKey + assocKey.AttributeMap = fromClassMap.getAttributeMapByString(attrName.Value, False) + assocKey.ColumnMap = New CColumnMap + With assocKey.ColumnMap + .IsFind = False + .IsIdentity = False + .IsNullable = False + .Name = attrColumn.Value + 'Assume that dbtypes in the mapping table match dbtypes of data table + .ProviderType = assocKey.AttributeMap.ColumnMap.ProviderType + .StorageSize = assocKey.AttributeMap.ColumnMap.StorageSize + .StorageType = assocKey.AttributeMap.ColumnMap.StorageType + .TableMap = New CTableMap + .TableMap.Name = assocTable.Name + .TableMap.TableOwner = assocTable.TableOwner + End With + assocTable.FromKeys.Add(assocKey) + End If + ElseIf elementChild2.Name = "toClassKey" Then + attrName = elementChild2.GetAttributeNode("name") + attrColumn = elementChild2.GetAttributeNode("column") + If Not attrName Is Nothing And Not attrColumn Is Nothing Then + assocKey = New CAssociationKey + assocKey.AttributeMap = toClassMap.getAttributeMapByString(attrName.Value, False) + assocKey.ColumnMap = New CColumnMap + With assocKey.ColumnMap + .IsFind = False + .IsIdentity = False + .IsNullable = False + .Name = attrColumn.Value + .ProviderType = assocKey.AttributeMap.ColumnMap.ProviderType + .StorageSize = assocKey.AttributeMap.ColumnMap.StorageSize + .StorageType = assocKey.AttributeMap.ColumnMap.StorageType + End With + assocTable.ToKeys.Add(assocKey) + End If + End If + End If + nodeChild2 = nodeChild2.NextSibling + Loop + udaAm.AssocationTable = assocTable End If + End If End If nodeChild = nodeChild.NextSibling Loop fromClassMap.addAssociationMap(udaAm) + 'Many to many associations need to be added to both class maps + If udaAm.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY AndAlso Not udaAm.ToClassTarget Is Nothing Then + toClassMap.addAssociationMap(udaAm) + End If Else - Throw New XMLMappingException([String].Format("Error in association definition: Missing FromClass({0}), ToClass({1}) or Target({2}) attributes", attrFromClass, attrToClass, attrTarget)) + Throw New XMLMappingException([String].Format("Error in association definition: Missing FromClass({0}), ToClass({1}) or Target({2}) attributes", attrFromClass, attrToClass, attrFromTarget)) End If End Sub End Class \ No newline at end of file --- NEW FILE: CAssociationTable.vb --- Public Class CAssociationTable Private m_name As String Private m_owner As String Private m_fromKeys As New CAssociationKeys Private m_toKeys As New CAssociationKeys 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 TableOwner() As String Get Return m_owner End Get Set(ByVal Value As String) m_owner = Value End Set End Property Public Property FromKeys() As CAssociationKeys Get Return m_fromKeys End Get Set(ByVal Value As CAssociationKeys) m_fromKeys = Value End Set End Property Public Property ToKeys() As CAssociationKeys Get Return m_toKeys End Get Set(ByVal Value As CAssociationKeys) m_toKeys = Value End Set End Property End Class Index: CJoin.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CJoin.vb,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- CJoin.vb 15 Dec 2004 23:46:11 -0000 1.10 +++ CJoin.vb 9 Feb 2005 06:24:44 -0000 1.11 @@ -275,6 +275,9 @@ Dim leftBracket As String = "(" Dim rightBracket As String = ")" Dim isFirst As Boolean = True + Dim wrkAlias As String + Dim wrkKey As CAssociationKey + Dim fromKeys, toKeys As CAssociationKeys If LeftSide Is Nothing Then tm = CType(RightSide.Tables.Item(1), CTableMap) @@ -294,10 +297,8 @@ If i > 1 Then s = s & " " & db.getClauseStringAnd & " " End If - 's = s & cm.getReferenceAttributeMap(i).ColumnMap.getAliasQualifiedName(LeftSide.RootTableAlias) _ - ' & " = " & cm.getReferenceAttributeMap(i).AttributeMap.ColumnMap.getAliasQualifiedName(TableAlias) s = s & cm.getReferenceAttributeMap(i).ColumnMap.getAliasQualifiedName(LeftTableAlias) _ - & " = " & cm.getReferenceAttributeMap(i).AttributeMap.ColumnMap.getAliasQualifiedName(TableAlias) + & " = " & cm.getReferenceAttributeMap(i).AttributeMap.ColumnMap.getAliasQualifiedName(TableAlias) Next i s = s & rightBracket ElseIf Association Is Nothing Then @@ -328,19 +329,58 @@ rightBracket = "" End If tm = CType(cm.Tables.Item(1), CTableMap) - s = leftBracket & LeftSide.GetSQLString & " " & db.getClauseStringLeftJoin _ - & " " & db.getClauseStringTableAlias(tm.Name, tm.TableOwner, TableAlias) & " " & db.getClauseStringOn & " " - For i = 1 To CType(Association.Entries.Count, Short) - If i > 1 Then - s = s & " " & db.getClauseStringAnd & " " - End If - udaEntry = Association.getEntry(i) - 's = s & udaEntry.FromAttrMap.ColumnMap.getAliasQualifiedName(LeftSide.RootTableAlias) & " = " _ - '& udaEntry.ToAttrMap.ColumnMap.getAliasQualifiedName(TableAlias) - s = s & udaEntry.FromAttrMap.ColumnMap.getAliasQualifiedName(LeftTableAlias) & " = " _ + 'if one-to-many or one-to-one association code stays as it was + If Association.Cardinality <> CUDAMap.CardinalityEnum.MANY_TO_MANY Then + s = leftBracket & LeftSide.GetSQLString & " " & db.getClauseStringLeftJoin _ + & " " & db.getClauseStringTableAlias(tm.Name, tm.TableOwner, TableAlias) & " " & db.getClauseStringOn & " " + For i = 1 To CType(Association.Entries.Count, Short) + If i > 1 Then + s = s & " " & db.getClauseStringAnd & " " + End If + udaEntry = Association.getEntry(i) + s = s & udaEntry.FromAttrMap.ColumnMap.getAliasQualifiedName(LeftTableAlias) & " = " _ & udaEntry.ToAttrMap.ColumnMap.getAliasQualifiedName(TableAlias) - Next i - s = s & rightBracket + Next i + s = s & rightBracket + Else + 'Many to many joins must first join with the association table + 'We will append an 'x' to the alias for unique table names + + 'First determine which key set should be used (ie is this the association from or to class) + If Association.FromClass.Name = m_rightSide.Name Then + toKeys = Association.AssocationTable.FromKeys + fromKeys = Association.AssocationTable.ToKeys + Else + fromKeys = Association.AssocationTable.FromKeys + toKeys = Association.AssocationTable.ToKeys + End If + + 'Also we need to prepend two left brackets since we are adding two joins + s = leftBracket & leftBracket & LeftSide.GetSQLString & " " & db.getClauseStringLeftJoin + 'Add the association table + wrkAlias = TableAlias & "x" + s &= " " & db.getClauseStringTableAlias(Association.AssocationTable.Name, Association.AssocationTable.TableOwner, wrkAlias) & " " & db.getClauseStringOn & " " + For i = 1 To CType(fromKeys.Count, Short) + If i > 1 Then + s = s & " " & db.getClauseStringAnd & " " + End If + wrkKey = fromKeys.Item(i - 1) + s &= wrkKey.AttributeMap.ColumnMap.getAliasQualifiedName(LeftTableAlias) & " = " _ + & wrkAlias & "." & wrkKey.ColumnMap.Name + Next i + + 'Now add the class + s &= rightBracket & " " & db.getClauseStringLeftJoin + s &= " " & db.getClauseStringTableAlias(tm.Name, tm.TableOwner, TableAlias) & " " & db.getClauseStringOn & " " + For i = 1 To CType(toKeys.Count, Short) + If i > 1 Then + s = s & " " & db.getClauseStringAnd & " " + End If + wrkKey = toKeys.Item(i - 1) + s &= wrkAlias & "." & wrkKey.ColumnMap.Name & " = " & wrkKey.AttributeMap.ColumnMap.getAliasQualifiedName(TableAlias) + Next i + s = s & rightBracket + End If End If End If Return s Index: CInjectedObject.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CInjectedObject.vb,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- CInjectedObject.vb 4 Feb 2005 04:39:20 -0000 1.10 +++ CInjectedObject.vb 9 Feb 2005 06:24:44 -0000 1.11 @@ -583,9 +583,9 @@ 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)) - ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - obj.SetAttributeValue(udamap.Target, Me.getCollectionByAttribute(udamap.Target)) + obj.SetAttributeValue(udamap.FromClassTarget, Me.getObjectByAttribute(udamap.FromClassTarget)) + ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Or udamap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY Then + obj.SetAttributeValue(udamap.FromClassTarget, Me.getCollectionByAttribute(udamap.FromClassTarget)) End If 'End If Next i @@ -603,9 +603,9 @@ 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)) - ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then - obj.SetAttributeValue(udamap.Target, Me.getCollectionByAttribute(udamap.Target)) + obj.SetAttributeValue(udamap.FromClassTarget, Me.getObjectByAttribute(udamap.FromClassTarget)) + ElseIf udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Or udamap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY Then + obj.SetAttributeValue(udamap.FromClassTarget, Me.getCollectionByAttribute(udamap.FromClassTarget)) End If 'End If Next i Index: CClassMap.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CClassMap.vb,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- CClassMap.vb 19 Dec 2004 22:43:17 -0000 1.48 +++ CClassMap.vb 9 Feb 2005 06:24:44 -0000 1.49 @@ -41,7 +41,6 @@ Private m_associationMaps As HybridDictionary Private m_relationalDatabase As _CRelationalDatabase Private m_superClass As CClassMap - Private m_inverseAssociationMaps As Collection Private m_straightAssociationMaps As Collection Private m_findAttributeMaps As Collection Private m_identityAttributeMaps As Collection @@ -402,26 +401,6 @@ '''----------------------------------------------------------------------------- ''' <summary> - ''' Collection of inverse associations - ''' </summary> - ''' <value>A collection of assocation maps</value> - ''' <remarks>This collection contains all of the associations marked as Inverse="True" in - ''' the XML mapping.</remarks> - ''' <history> - ''' [rbanks] 27/11/2003 Created - ''' </history> - '''----------------------------------------------------------------------------- - Public Property InverseAssociationMaps() As Collection - Get - InverseAssociationMaps = m_inverseAssociationMaps - End Get - Set(ByVal Value As Collection) - m_inverseAssociationMaps = Value - End Set - End Property - - '''----------------------------------------------------------------------------- - ''' <summary> ''' Indicates whether the class is marked as a Read Only class. ''' </summary> ''' <value>Boolean indicating the classes read only status</value> @@ -518,7 +497,7 @@ ''' A collection of standard association maps. ''' </summary> ''' <value>A collection of association maps</value> - ''' <remarks>Contains association maps that are not marked as Inverse.</remarks> + ''' <remarks>Contains association maps</remarks> ''' <history> ''' [rbanks] 27/11/2003 Created ''' </history> @@ -633,7 +612,6 @@ m_associationMaps = New HybridDictionary m_referenceAttributeMaps = New Collection m_Tables = New Collection - m_inverseAssociationMaps = New Collection m_straightAssociationMaps = New Collection m_findAttributeMaps = New Collection m_identityAttributeMaps = New Collection @@ -652,20 +630,14 @@ ''' Adds an association map to the class map ''' </summary> ''' <param name="map">The association map to add</param> - ''' <remarks>Adds the association map to the class. The Inverse flag of the - ''' map is checked and the association map is also added to either the Inverse or - ''' Straight association maps.</remarks> + ''' <remarks>Adds the association map to the class.</remarks> ''' <history> ''' [rbanks] 27/11/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub addAssociationMap(ByVal map As CUDAMap) m_associationMaps.Add(map.Name, map) - If map.Inverse Then - m_inverseAssociationMaps.Add(map) - Else - m_straightAssociationMaps.Add(map) - End If + m_straightAssociationMaps.Add(map) End Sub '''----------------------------------------------------------------------------- @@ -978,7 +950,7 @@ statement.addSqlClause(Me.RelationalDatabase.getClauseStringSelect) If rowLimit > 0 And Me.RelationalDatabase.limitClauseAtStart Then statement.addSqlClause(" " & Me.RelationalDatabase.getClauseStringLimit) - If rowOffset > 0 andalso Me.RelationalDatabase.supportsSelectOffsets Then + If rowOffset > 0 AndAlso Me.RelationalDatabase.supportsSelectOffsets Then statement.addSqlClause(" " & Str(rowOffset) & ",") End If statement.addSqlClause(" " & Str(rowLimit)) @@ -1669,7 +1641,7 @@ '''----------------------------------------------------------------------------- ''' <summary> - ''' Gets the number of non-inverse associations for the class maop + ''' Gets the number of associations for the class maop ''' </summary> ''' <returns>The number of standard associations</returns> ''' <remarks>None.</remarks> @@ -1683,20 +1655,6 @@ '''----------------------------------------------------------------------------- ''' <summary> - ''' Gets the number of inverse associations for the class maop - ''' </summary> - ''' <returns>The number of inverse associations</returns> - ''' <remarks>None.</remarks> - ''' <history> - ''' [rbanks] 27/11/2003 Created - ''' </history> - '''----------------------------------------------------------------------------- - Public Function getInverseAssociationMapSize() As Short - getInverseAssociationMapSize = m_inverseAssociationMaps.Count() - End Function - - '''----------------------------------------------------------------------------- - ''' <summary> ''' Gets a specific association map from the class map ''' </summary> ''' <param name="index">The index position of the association map.</param> @@ -1714,23 +1672,6 @@ '''----------------------------------------------------------------------------- ''' <summary> - ''' Gets a specific Inverse association map from the class map - ''' </summary> - ''' <param name="index">The index position of the association map.</param> - ''' <returns>The Inverse association map at the specified position</returns> - ''' <remarks>None.</remarks> - ''' <history> - ''' [rbanks] 27/11/2003 Created - ''' </history> - '''----------------------------------------------------------------------------- - Public Function getInverseAssociationMap(ByVal index As Short) As CUDAMap - Dim udaMap As CUDAMap - udaMap = Me.InverseAssociationMaps.Item(index) - getInverseAssociationMap = udaMap - End Function - - '''----------------------------------------------------------------------------- - ''' <summary> ''' Gets SQL text for processing inheritance associations. ''' </summary> ''' <returns>A string containing the SQL statement.</returns> @@ -1811,7 +1752,7 @@ For Each de In oneClassMap.AssociationMaps udamap = de.Value - If udamap.FromClass.Equals(oneClassMap) And udamap.ForClass.Equals(manyClassMap) And udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then + If udamap.FromClass.Equals(oneClassMap) And udamap.ToClass.Equals(manyClassMap) And udamap.Cardinality = CUDAMap.CardinalityEnum.ONE_TO_MANY Then Return True End If Next @@ -1871,10 +1812,16 @@ If udamap.RetrieveAutomatic Then classMapCount += 1 mapName = "t" & classMapCount.ToString - rMaps.Add(mapName, udamap.ForClass) - m_joinSet = New CJoin(m_joinSet, udamap.ForClass, mapName, udamap) - 'Add joins for multiple inheritance - pbroker.createJoinForMultipleInheritance(udamap.ForClass, classMapCount, m_joinSet, rMaps) + If udamap.Cardinality = CUDAMap.CardinalityEnum.MANY_TO_MANY AndAlso Me.Name <> udamap.FromClass.Name Then + rMaps.Add(mapName, udamap.ToClass) + m_joinSet = New CJoin(m_joinSet, udamap.FromClass, mapName, udamap) + pbroker.createJoinForMultipleInheritance(udamap.FromClass, classMapCount, m_joinSet, rMaps) + Else + rMaps.Add(mapName, udamap.ToClass) + m_joinSet = New CJoin(m_joinSet, udamap.ToClass, mapName, udamap) + 'Add joins for multiple inheritance + pbroker.createJoinForMultipleInheritance(udamap.ToClass, classMapCount, m_joinSet, rMaps) + End If End If Next @@ -1994,10 +1941,10 @@ If udamap.RetrieveAutomatic Then classMapCount += 1 mapName = "t" & classMapCount.ToString - rMaps.Add(mapName, udamap.ForClass) - m_joinSet = New CJoin(m_joinSet, udamap.ForClass, mapName, udamap) + rMaps.Add(mapName, udamap.ToClass) + m_joinSet = New CJoin(m_joinSet, udamap.ToClass, mapName, udamap) 'Add joins for multiple inheritance - pbroker.createJoinForMultipleInheritance(udamap.ForClass, classMapCount, m_joinSet, rMaps) + pbroker.createJoinForMultipleInheritance(udamap.ToClass, classMapCount, m_joinSet, rMaps) End If Next Index: CMultiSummaryCriteria.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CMultiSummaryCriteria.vb,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- CMultiSummaryCriteria.vb 28 Oct 2004 00:16:12 -0000 1.12 +++ CMultiSummaryCriteria.vb 9 Feb 2005 06:24:44 -0000 1.13 @@ -265,7 +265,7 @@ For i = 0 To UBound(myArrayStrings) - 1 strName = myArrayStrings(i) udaMap = clMap.AssociationMaps(strName) - clMap = udaMap.ForClass + clMap = udaMap.toclass If clMap Is Nothing Then Exit For End If Index: XMLMapping.xsd =================================================================== RCS file: /cvsroot/jcframework/dotnet/XMLMapping.xsd,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- XMLMapping.xsd 7 Feb 2005 07:37:35 -0000 1.2 +++ XMLMapping.xsd 9 Feb 2005 06:24:45 -0000 1.3 @@ -63,11 +63,11 @@ <xs:attribute name="fromClass" form="unqualified" type="xs:string" use="required" /> <xs:attribute name="toClass" form="unqualified" type="xs:string" use="required" /> <xs:attribute name="cardinality" form="unqualified" type="cardinality" use="required" /> - <xs:attribute name="target" form="unqualified" type="xs:string" use="required" /> + <xs:attribute name="fromClassTarget" form="unqualified" type="xs:string" use="required" /> + <xs:attribute name="toClassTarget" form="unqualified" type="xs:string" /> <xs:attribute name="retrieveAutomatic" form="unqualified" type="TrueFalse" use="required" /> <xs:attribute name="deleteAutomatic" form="unqualified" type="TrueFalse" use="required" /> <xs:attribute name="saveAutomatic" form="unqualified" type="TrueFalse" use="required" /> - <xs:attribute name="inverse" form="unqualified" type="TrueFalse" /> <xs:attribute name="fromClassNameSpace" type="xs:string" /> <xs:attribute name="toClassNameSpace" type="xs:string" /> </xs:complexType> --- NEW FILE: CAssociationKey.vb --- Public Class CAssociationKey Private m_attributemap As CAttributeMap Private m_columnname As CColumnMap Public Property AttributeMap() As CAttributeMap Get Return m_attributemap End Get Set(ByVal Value As CAttributeMap) m_attributemap = Value End Set End Property Public Property ColumnMap() As CColumnMap Get Return m_columnname End Get Set(ByVal Value As CColumnMap) m_columnname = Value End Set End Property End Class Public Class CAssociationKeys Inherits CollectionBase Public Sub Add(ByVal key As CAssociationKey) list.Add(key) End Sub Default Public ReadOnly Property Item(ByVal index As Integer) As CAssociationKey Get Return CType(list.Item(index), CAssociationKey) End Get End Property End Class --- NEW FILE: CAssociationObject.vb --- 'private object used for saving table entries in many-to-many associations Friend Class CAssociationObject Private m_objA As IPersistableObject Private m_objB As IPersistableObject Private m_classMapA As CClassMap Private m_classMapB As CClassMap Private m_association As CUDAMap Private m_objACol As Collection Private m_objBCol As Collection Private m_deleteNeeded As Boolean Public Property ObjectA() As IPersistableObject Get Return m_objA End Get Set(ByVal Value As IPersistableObject) m_objA = Value If Not m_objB Is Nothing AndAlso Not m_objA Is Nothing Then checkifdeletewillbeneeded() End If End Set End Property Public Property ClassMapA() As CClassMap Get Return m_classMapA End Get Set(ByVal Value As CClassMap) m_classMapA = Value End Set End Property Public Property ObjectB() As IPersistableObject Get Return m_objB End Get Set(ByVal Value As IPersistableObject) m_objB = Value If Not m_objA Is Nothing AndAlso Not m_objB Is Nothing Then checkifdeletewillbeneeded() End If End Set End Property Public Property ClassMapB() As CClassMap Get Return m_classMapB End Get Set(ByVal Value As CClassMap) m_classMapB = Value End Set End Property Public Property Association() As CUDAMap Get Return m_association End Get Set(ByVal Value As CUDAMap) m_association = Value End Set End Property Public ReadOnly Property DeleteNeeded() As Boolean Get Return m_deleteNeeded End Get End Property Public Function getInsertSql() As CSqlStatement Dim isFirst As Boolean Dim db As _CRelationalDatabase Dim m_insertStatement As New CSqlStatement Dim paramCount As Integer Dim AttrMap As CAttributeMap Dim Key As CAssociationKey Dim fromObj, toObj As IPersistableObject Dim i As Short db = m_classMapA.RelationalDatabase 'Determine which order classes are in If m_classMapA.Name = m_association.FromClass.Name Then fromObj = m_objA toObj = m_objB Else fromObj = m_objB toObj = m_objA End If m_insertStatement.addSqlClause(db.getClauseStringInsert & " ") m_insertStatement.addSqlClause(m_association.AssocationTable.Name & " ") m_insertStatement.addSqlClause("(") isFirst = True For i = 0 To m_association.AssocationTable.FromKeys.Count - 1 Key = m_association.AssocationTable.FromKeys.Item(i) If isFirst Then m_insertStatement.addSqlClause(Key.ColumnMap.Name) isFirst = False Else m_insertStatement.addSqlClause(", " & Key.ColumnMap.Name) End If Next i For i = 0 To m_association.AssocationTable.ToKeys.Count - 1 Key = m_association.AssocationTable.ToKeys.Item(i) If isFirst Then m_insertStatement.addSqlClause(Key.ColumnMap.Name) isFirst = False Else m_insertStatement.addSqlClause(", " & Key.ColumnMap.Name) End If Next i m_insertStatement.addSqlClause(") ") m_insertStatement.addSqlClause(db.getClauseStringValues & " ") m_insertStatement.addSqlClause("(") isFirst = True For i = 1 To (m_association.AssocationTable.FromKeys.Count + m_association.AssocationTable.FromKeys.Count) If isFirst Then m_insertStatement.addSqlClause(db.getParamHolder(i)) isFirst = False Else m_insertStatement.addSqlClause(", " & db.getParamHolder(i)) End If Next i m_insertStatement.addSqlClause(")") 'Add parameter values paramCount = 1 For i = 0 To m_association.AssocationTable.FromKeys.Count - 1 Key = m_association.AssocationTable.FromKeys.Item(i) m_insertStatement.addSqlParameter(paramCount, fromObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i For i = 0 To m_association.AssocationTable.ToKeys.Count - 1 Key = m_association.AssocationTable.ToKeys.Item(i) m_insertStatement.addSqlParameter(paramCount, toObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i Return m_insertStatement End Function Public Function getDeleteSql() As CSqlStatement Dim isFirst As Boolean Dim db As _CRelationalDatabase Dim m_deleteStatement As New CSqlStatement Dim paramCount As Integer Dim AttrMap As CAttributeMap Dim Key As CAssociationKey Dim fromObj, toObj As IPersistableObject Dim i As Short db = m_classMapA.RelationalDatabase 'Determine which order classes are in If m_classMapA.Name = m_association.FromClass.Name Then fromObj = m_objA toObj = m_objB Else fromObj = m_objB toObj = m_objA End If m_deleteStatement.addSqlClause(db.getClauseStringDelete & " " & db.getClauseStringFrom & " ") m_deleteStatement.addSqlClause(m_association.AssocationTable.Name & " ") m_deleteStatement.addSqlClause(db.getClauseStringWhere & " ") paramCount = 1 For i = 0 To m_association.AssocationTable.FromKeys.Count - 1 Key = m_association.AssocationTable.FromKeys.Item(i) If i > 1 Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) m_deleteStatement.addSqlParameter(paramCount, fromObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i For i = 0 To m_association.AssocationTable.ToKeys.Count - 1 Key = m_association.AssocationTable.ToKeys.Item(i) If i > 1 Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) m_deleteStatement.addSqlParameter(paramCount, fromObj.GetValueByAttribute(Key.AttributeMap.Name), Key.ColumnMap) paramCount += 1 Next i Dim x As String = m_deleteStatement.SqlString Dim p As CSQLParameter For i = 1 To paramCount p = m_deleteStatement.Parameters.Item(i) If IsNullAlias(p.Value) Then If db.UseANSINulls = True Then x = x.Replace(" = _" & i.ToString & "_", " is NULL") p.Ignore = True Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Next m_deleteStatement.SqlString = x Return m_deleteStatement End Function Public Function getDeleteSqlUsingOriginalValues() As CSqlStatement Dim isFirst As Boolean Dim db As _CRelationalDatabase Dim m_deleteStatement As New CSqlStatement Dim paramCount As Integer Dim AttrMap As CAttributeMap Dim Key As CAssociationKey Dim fromObj, toObj As IPersistableObject Dim fromCol, toCol As Collection Dim i As Short db = m_classMapA.RelationalDatabase 'Determine which order classes are in If m_classMapA.Name = m_association.FromClass.Name Then fromObj = m_objA toObj = m_objB fromCol = m_objACol toCol = m_objBCol Else fromObj = m_objB toObj = m_objA toCol = m_objACol fromCol = m_objBCol End If m_deleteStatement.addSqlClause(db.getClauseStringDelete & " " & db.getClauseStringFrom & " ") m_deleteStatement.addSqlClause(m_association.AssocationTable.Name & " ") m_deleteStatement.addSqlClause(db.getClauseStringWhere & " ") paramCount = 1 For i = 0 To m_association.AssocationTable.FromKeys.Count - 1 Key = m_association.AssocationTable.FromKeys.Item(i) If i > 1 Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) m_deleteStatement.addSqlParameter(paramCount, fromCol.Item(i), Key.ColumnMap) paramCount += 1 Next i For i = 0 To m_association.AssocationTable.ToKeys.Count - 1 Key = m_association.AssocationTable.ToKeys.Item(i) If i > 1 Then m_deleteStatement.addSqlClause(" " & db.getClauseStringAnd & " ") End If m_deleteStatement.addSqlClause(Key.ColumnMap.getFullyQualifiedName & db.getClauseStringEqualTo("_" & i.ToString & "_")) m_deleteStatement.addSqlParameter(paramCount, toCol.Item(i), Key.ColumnMap) paramCount += 1 Next i Dim x As String = m_deleteStatement.SqlString Dim p As CSQLParameter For i = 1 To paramCount p = m_deleteStatement.Parameters.Item(i) If IsNullAlias(p.Value) Then If db.UseANSINulls = True Then x = x.Replace(" = _" & i.ToString & "_", " is NULL") p.Ignore = True Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Else x = x.Replace("_" & i.ToString & "_", db.getParamHolder(i)) End If Next m_deleteStatement.SqlString = x Return m_deleteStatement End Function Private Sub CheckIfDeleteWillBeNeeded() Dim i As Integer Dim attrMap As CAttributeMap Dim Value, Value2 As Object m_deleteNeeded = False If Not m_objA.OriginalCacheKey Is Nothing AndAlso Not m_objB.OriginalCacheKey Is Nothing Then 'Copy values while looking for changes For i = 1 To m_objA.GetClassMap.getKeySize attrMap = m_objA.GetClassMap.getKeyAttributeMap(i) Value = m_objA.OriginalCacheKey.GetKeyValue(i) Value2 = m_objA.GetValueByAttribute(attrMap.Name) m_objACol.Add(Value) Try If Not Value Is Nothing AndAlso Not Value2 Is Nothing Then If Not Value.Equals(Value2) Then m_deleteNeeded = True End If End If Catch ex As Exception End Try Next For i = 1 To m_objB.GetClassMap.getKeySize attrMap = m_objB.GetClassMap.getKeyAttributeMap(i) Value = m_objB.OriginalCacheKey.GetKeyValue(i) Value2 = m_objB.GetValueByAttribute(attrMap.Name) m_objBCol.Add(Value) Try If Not Value Is Nothing AndAlso Not Value2 Is Nothing Then If Not Value.Equals(Value2) Then m_deleteNeeded = True End If End If Catch ex As Exception End Try Next End If End Sub End Class Index: CCriteriaCondition.vb =================================================================== RCS file: /cvsroot/jcframework/dotnet/CCriteriaCondition.vb,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- CCriteriaCondition.vb 28 Oct 2004 00:16:12 -0000 1.16 +++ CCriteriaCondition.vb 9 Feb 2005 06:24:44 -0000 1.17 @@ -333,7 +333,7 @@ udaMap = clMap.AssociationMaps(strName) m_Associations.Add(udaMap) - clMap =... [truncated message content] |
From: Richard B. <rb...@us...> - 2005-02-09 06:21:04
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28234/InheritedClasses Added Files: ManyToManyClasses_v2.vb ManyToManyTests_v2.vb Log Message: Unit test for new Many-to-Many associations --- NEW FILE: ManyToManyClasses_v2.vb --- Imports AToMSFramework Namespace InheritedClasses #Region "M2MA" Public Class M2MA Inherits CPersistentObject Private _description As String Private _bCol As M2MBCollection Public Property Description() As String Get Return _description End Get Set(ByVal Value As String) _description = Value SetDirtyFlag() End Set End Property Public Property M2MBCollection() As M2MBCollection Get Return _bCol End Get Set(ByVal Value As M2MBCollection) _bCol = Value End Set End Property Public Overrides Function getNewObject() As AToMSFramework.CPersistentObject Return New M2MA End Function Public Overrides Function IsValid() As Boolean Return True End Function Public Sub New() _bCol = New M2MBCollection _bCol.ContainerObject = Me End Sub End Class #End Region #Region "M2MB" Public Class M2MB Inherits CPersistentObject Private _description As String Private _aCol As M2MACollection Public Property Description() As String Get Return _description End Get Set(ByVal Value As String) _description = Value SetDirtyFlag() End Set End Property Public Property M2MACollection() As M2MACollection Get Return _aCol End Get Set(ByVal Value As M2MACollection) _aCol = Value End Set End Property Public Overrides Function getNewObject() As AToMSFramework.CPersistentObject Return New M2MB End Function Public Overrides Function IsValid() As Boolean Return True End Function Public Sub New() _aCol = New M2MACollection _aCol.ContainerObject = Me End Sub End Class #End Region #Region "M2MACollection" Public Class M2MACollection Inherits CPersistentCollection Public Overloads Sub Add(ByVal a As M2MA) list.Add(a) End Sub Public Shadows Function Item(ByVal index As Integer) As M2MA Return CType(MyBase.Item(index), M2MA) End Function End Class #End Region #Region "M2MBCollection" Public Class M2MBCollection Inherits CPersistentCollection Public Overloads Sub Add(ByVal b As M2MB) list.Add(b) End Sub Public Shadows Function Item(ByVal index As Integer) As M2MB Return CType(MyBase.Item(index), M2MB) End Function End Class #End Region End Namespace --- NEW FILE: ManyToManyTests_v2.vb --- Imports AToMSFramework Imports NUnit.Framework Namespace InheritedClasses <TestFixture()> Public Class ManyToManyTests_v2 Private pbroker As CPersistenceBroker Private A As M2MA Private B As M2MB <TestFixtureSetUp()> Public Sub Init() Environment.CurrentDirectory = System.AppDomain.CurrentDomain.BaseDirectory Dim retry As Boolean = True While retry = True Try 'Remove any existing test database System.IO.File.Delete(".\db1.mdb") retry = False Catch iox As IO.IOException 'file is in use - so we will loop around until it is released GC.Collect() Catch ex As Exception retry = False End Try End While System.IO.File.Copy(".\original db1.mdb", ".\db1.mdb") pbroker = New CPersistenceBroker pbroker.init() End Sub <TestFixtureTearDown()> Public Sub Dispose() pbroker.Dispose() pbroker = Nothing End Sub <Test()> Public Sub SaveThenRetrieve() Dim gval As String Dim x As Integer, y As Integer A = New M2MA A.Description = "A-one" gval = A.GUIDValue B = New M2MB B.Description = "B-one" A.M2MBCollection.Add(B) B.M2MACollection.Add(A) Dim B2 As M2MB = New M2MB B2.Description = "B-two" A.M2MBCollection.Add(B2) Dim A2 As M2MA = New M2MA A2.Description = "A-two" B2.M2MACollection.Add(A2) A.Save() pbroker.ClearCache() A = New M2MA A.GUIDValue = gval A.Retrieve() Assert.AreEqual(2, A.M2MBCollection.Count) 'Order of guids can affect order of the collection If A.M2MBCollection.Item(0).M2MACollection.Count = 1 Then x = 0 y = 1 Else x = 1 y = 0 End If B = A.M2MBCollection.Item(x) Assert.IsNotNull(B) Assert.AreEqual("B-one", B.Description) Assert.AreEqual(1, B.M2MACollection.Count) Assert.IsTrue(A.Equals(B.M2MACollection.Item(0))) B = A.M2MBCollection.Item(y) Assert.IsNotNull(B) Assert.AreEqual("B-two", B.Description) Assert.AreEqual(2, B.M2MACollection.Count) End Sub End Class End Namespace |
From: Richard B. <rb...@us...> - 2005-02-09 06:21:04
|
Update of /cvsroot/jcframework/Nunit In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28234 Modified Files: AtomsFramework.xml Nunit_AtomsFramework.vbproj Nunit_AtomsFramework.vbproj.user original db1.mdb Log Message: Unit test for new Many-to-Many associations Index: Nunit_AtomsFramework.vbproj =================================================================== RCS file: /cvsroot/jcframework/Nunit/Nunit_AtomsFramework.vbproj,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- Nunit_AtomsFramework.vbproj 17 Dec 2004 03:27:47 -0000 1.15 +++ Nunit_AtomsFramework.vbproj 9 Feb 2005 06:20:47 -0000 1.16 @@ -165,11 +165,21 @@ BuildAction = "Compile" /> <File + RelPath = "InheritedClasses\ManyToManyClasses_v2.vb" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "InheritedClasses\ManyToManyTests.vb" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "InheritedClasses\ManyToManyTests_v2.vb" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "InheritedClasses\MultiRetrieveTestClasses.vb" SubType = "Code" BuildAction = "Compile" Index: original db1.mdb =================================================================== RCS file: /cvsroot/jcframework/Nunit/original db1.mdb,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 Binary files /tmp/cvsL7pJ1Y and /tmp/cvsIoZ90O differ Index: AtomsFramework.xml =================================================================== RCS file: /cvsroot/jcframework/Nunit/AtomsFramework.xml,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- AtomsFramework.xml 7 Feb 2005 22:07:15 -0000 1.16 +++ AtomsFramework.xml 9 Feb 2005 06:20:47 -0000 1.17 @@ -363,4 +363,27 @@ <entry fromAttribute="Name" toAttribute="ReportsToName"/> </association> + <class name="M2MA" table="ManyToManyA" database="MSA" namespace="NunitTests.InheritedClasses"> + <attribute name="GUIDValue" column="GuidValue" key="primary"/> + <attribute name="Description" column="description" /> + <attribute name="M2MBCollection" /> + </class> + <class name="M2MB" table="ManyToManyB" database="MSA" namespace="NunitTests.InheritedClasses"> + <attribute name="GUIDValue" column="GuidValue" key="primary"/> + <attribute name="Description" column="description" /> + <attribute name="M2MACollection" /> + </class> + <association fromClass="NunitTests.InheritedClasses.M2MA" + toClass="NunitTests.InheritedClasses.M2MB" + cardinality="ManyToMany" + fromClassTarget="M2MBCollection" + toClassTarget="M2MACollection" + retrieveAutomatic="true" saveAutomatic="true" deleteAutomatic="true"> + <associationTable name="ManyToManyAB"> + <fromClassKey name="GUIDValue" column="AGuidValue" /> + <toClassKey name="GUIDValue" column="BGuidValue" /> + </associationTable> + </association> + + </map> \ No newline at end of file Index: Nunit_AtomsFramework.vbproj.user =================================================================== RCS file: /cvsroot/jcframework/Nunit/Nunit_AtomsFramework.vbproj.user,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Nunit_AtomsFramework.vbproj.user 18 Oct 2004 00:07:10 -0000 1.1 +++ Nunit_AtomsFramework.vbproj.user 9 Feb 2005 06:20:47 -0000 1.2 @@ -13,7 +13,7 @@ StartAction = "Program" StartArguments = '"..\Nunit_AtomsFramework.nunit"' StartPage = "" - StartProgram = "C:\Program Files\NUnit 2.2\bin\nunit-gui.exe" + StartProgram = "C:\Program Files\NUnit 2.2.2\bin\nunit-gui.exe" StartURL = "" StartWorkingDirectory = "" StartWithIE = "true" |
From: Richard B. <rb...@us...> - 2005-02-07 23:29:59
|
Update of /cvsroot/jcframework/dotnet/Providers/AF_Firebird In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24084/Providers/AF_Firebird Added Files: AF_Firebird.vbproj AssemblyInfo.vb CFirebirdConnection.vb CFirebirdDatabase.vb Log Message: Added initial Firebird support (usng 1.7 RC1 .net provider) --- NEW FILE: CFirebirdDatabase.vb --- Option Strict Off Option Explicit On Imports FirebirdSql.Data.Firebird Imports AToMSFramework '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CMsSqlDatabase ''' '''----------------------------------------------------------------------------- ''' <summary> ''' Implementation of CRelationalDatabase for Microsoft SQL Server. ''' </summary> ''' <remarks>This class contains the specific functionality required for the ''' framework to interact with Microsoft SQL databases.</remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Class CMsSqlDatabase Inherits CRelationalDatabase Private m_name As String Private m_user As String Private m_password As String Private m_serverName As String '''----------------------------------------------------------------------------- ''' <summary> ''' Establishes a new database connection. ''' </summary> ''' <returns>A CMSSqlConnection containing the newly established connection.</returns> ''' <remarks>The CMSSqlConnection class implements the _CConnection interface which ''' is required by this method. ''' <para>If the connection cannot be established an exception will be thrown.</para> ''' <para>The connection is established using normal SQL server authentication (ie ''' Integrated security is false, and persiste security info is false.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getNewConnection() As _CConnection Dim conn As New CFirebirdConnection conn.Connection = New FbConnection conn.ManageTransactions = True Try If m_user Is Nothing OrElse m_user.Length = 0 Then m_user = "" m_password = "" Dim pbroker As CPersistenceBroker pbroker = getPersistenceBrokerInstance() pbroker.GetLoginDetails(Me, m_user, m_password) End If conn.Connection.ConnectionString = _ "Data Source=" & m_serverName & ";" & _ "Initial Catalog=" & m_name & ";" & _ "Integrated Security=false;" & _ "Persist Security Info=False;" & _ "User Id=" & m_user & ";" & _ "Password=" & m_password conn.Connection.Open() Catch ex As FbException Throw New DatabaseConnectionException(ex.Message, ex) Catch ex As Exception Throw New DatabaseConnectionException(ex.Message, ex) End Try getNewConnection = conn End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Sets the initial properties of the database. ''' </summary> ''' <param name="properties">The property information supplied in the XML mapping file.</param> ''' <remarks>In order to initialise the database object properly the following must be supplied ''' <list type="bullet"> ''' <item><description>Name: The name of the database on the server (ie the catalog name)</description></item> ''' <item><description>ServerName: The name of the database server</description></item> ''' <item><description>User: The user name for secured databases.</description></item> ''' <item><description>Password: The password for secured databases.</description></item> ''' <item><description>OIDTable: The table name containing the OID A-value. Can be ignored if OIDs are not used.</description></item> ''' </list> ''' <para>If the database is used without having been properly initialised you are likely ''' to get exceptions thrown in your application.</para> ''' </remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Sub init(ByVal properties As System.Collections.Specialized.HybridDictionary) m_name = properties.Item("name") m_serverName = properties.Item("serverName") m_user = properties.Item("user") m_password = properties.Item("password") If properties.Item("ansinulls") Is Nothing Then UseANSINulls = False Else UseANSINulls = properties.Item("ansinulls") End If MyBase.OIDTable = properties.Item("OIDTable") End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' Gets the value of an object in a format the database can understand. ''' </summary> ''' <param name="tempValue">The object being evaluated.</param> ''' <returns>A string containing the SQL compatible value for the object</returns> ''' <remarks>The following rules are applied when converting object values into ''' database compatible strings ''' <para>Any value that is a Null Alias <see cref="M:AToMSFramework.ModAliasNull.IsNullAlias"/> ''' will be returned as NULL.</para> ''' <para>Strings are enclosed in single quotes. If the string is already enclosed in single quotes then ''' nothing is changed. Also, any single quotes within the string are converted to a pair of single quotes.</para> ''' <para>Dates are converted to yyyy-MM-dd HH:mm:ss format and enclosed in single quotes. If a datetime field ''' only has a time value, then a time-only string is returned instead.</para> ''' <para>Booleans are converted to 1 or 0</para> ''' <para>Numbers are converted to strings directly.</para> ''' <para>Objects that are nothing return a NULL and all other objects are directly converted to strings using their ''' inbuilt ToString methods.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getValueFor(ByVal tempValue As Object) As String Dim tempRetorno As String Dim dd As DateTime Dim OriginalCulture As System.Globalization.CultureInfo Dim TempCulture As System.Globalization.CultureInfo If IsNullAlias(tempValue) Then Return "NULL" Else Select Case VarType(tempValue) Case VariantType.String If Left(tempValue, 1) = "'" And Right(tempValue, 1) = "'" And CStr(tempValue).Length > 2 Then 'string already enclosed in quotes so ignore tempRetorno = tempValue Else 'replace single quote with double quote, and enclose entire string in quotes tempRetorno = "'" & Replace(tempValue, "'", "''") & "'" End If Case VariantType.Date TempCulture = New System.Globalization.CultureInfo("en-US") OriginalCulture = System.Threading.Thread.CurrentThread.CurrentCulture System.Threading.Thread.CurrentThread.CurrentCulture = TempCulture System.Threading.Thread.CurrentThread.CurrentUICulture = TempCulture dd = CType(tempValue, DateTime) If dd = Date.MinValue Then tempRetorno = "NULL" Else If dd.Date.Ticks = 0 Then 'MSSQL doesn't support dates with years less than 1753, so time only 'values that format to "0001-01-01 11:23:00" for example produce errors. 'If it's just a time we will only return time portion. tempRetorno = "'" & dd.ToString("HH:mm:ss") & "'" Else tempRetorno = "'" & dd.ToString("yyyy-MM-dd HH:mm:ss") & "'" End If End If System.Threading.Thread.CurrentThread.CurrentCulture = OriginalCulture System.Threading.Thread.CurrentThread.CurrentUICulture = OriginalCulture Case VariantType.Boolean tempRetorno = IIf(tempValue, "1", "0") Case VariantType.Single, VariantType.Double, VariantType.Decimal, VariantType.Decimal tempRetorno = tempValue.ToString Case Else tempRetorno = tempValue End Select End If getValueFor = tempRetorno End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Gets the next OID A-Value from the database. ''' </summary> ''' <returns>A integer containing the A-Value.</returns> ''' <remarks>A connection is established to the database and the OIDTable (specified in ''' the XML mapping) is queried and updated. The obtained A-Value is returned. ''' <para>Should an error occur a value of 0 will be returned.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getNextOIDAvalue() As Integer Dim rs As New DataSet Dim da As New FbDataAdapter Dim cb As FbCommandBuilder Dim aValue As Integer Dim row As System.Data.DataRow Dim p As FbParameter Dim initvals() As Object = {1} Dim x As OIDException Dim conn As CFirebirdConnection conn = Me.getConnection(Nothing) conn.AutoCommit = False conn.startTransaction() Try da.SelectCommand = New FbCommand("select oidAValue from " & Me.OIDTable, conn.Connection, conn.Transaction) cb = New FbCommandBuilder(da) da.Fill(rs, "oid") If rs.Tables(0).Rows.Count = 0 Then 'Seed with value = 1 row = rs.Tables(0).Rows.Add(initvals) aValue = 1 Else rs.Tables(0).Rows(0).Item(0) += 1 aValue = rs.Tables(0).Rows(0).Item(0) End If da.Update(rs, "oid") da.Dispose() conn.commit() Catch err As FbException conn.rollback() x = New OIDException(err.Message, err) Catch err As Exception conn.rollback() x = New OIDException(err.Message, err) Finally Me.freeConnection(conn) If Not x Is Nothing Then Throw x End If End Try Return aValue End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Method to get the last Identity value for the connection. ''' </summary> ''' <param name="conn">The connection to use.</param> ''' <returns>An integer containing the value of the last updated identity column</returns> ''' <remarks>If multiple identity columns were updated the return value will only contain ''' the value of the last identity column updated. ''' <para>Identity values are retrieved by querying the @@IDENTITY value.</para> ''' <para>Should an error occur an exception will be thrown.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getIdentityValue(ByVal conn As _CConnection) As Integer Dim rs As New DataSet Dim da As New FbDataAdapter Dim cb As FbCommandBuilder Dim aValue As Integer Dim connection As CFirebirdConnection connection = conn connection.AutoCommit = False Try da.SelectCommand = New FbCommand("select @@IDENTITY", connection.Connection, connection.Transaction) cb = New FbCommandBuilder(da) da.Fill(rs, "identity") If rs.Tables(0).Rows.Count = 0 Then Throw New IdentityValueException("Could not retrieve identity value") Else If IsDBNull(rs.Tables(0).Rows(0).Item(0)) Then aValue = 0 Else aValue = rs.Tables(0).Rows(0).Item(0) End If Debug.WriteLine("Returned Identity value: " & aValue.ToString) End If da.Dispose() Catch err As FbException Throw New IdentityValueException(err.Message, err) End Try Return aValue End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Returns the SQL syntax placeholder for a parameter ''' </summary> ''' <param name="i">The number of the parameter being added</param> ''' <returns>A string containing the SQL parameter placeholder</returns> ''' <remarks>Since the parameter is for an MSSQL connection only a the returned ''' string is in the format of @pxxx where xxx is the value of the input integer (i).</remarks> ''' <history> ''' [rbanks] 23/01/2004 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getParamHolder(ByVal i As Integer) As String Return "@p" & CStr(i) End Function Public Overrides Function limitClauseAtStart() As Boolean Return True End Function Public Overrides Function getClauseStringLimit() As String Return "TOP" End Function Public Overrides Function getClauseStringTableAlias(ByVal table As String, ByVal owner As String, ByVal pAlias As String) As String Return Me.m_name & "." & owner & "." & table & " as " & pAlias End Function Public Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If Not m_disposed Then If disposing Then Dim conn As CFirebirdConnection While ConnectionPool.Count > 0 conn = ConnectionPool.Pop conn.Dispose() End While m_disposed = True End If End If End Sub End Class --- NEW FILE: AF_Firebird.vbproj --- <VisualStudioProject> <VisualBasic ProjectType = "Local" ProductVersion = "7.10.3077" SchemaVersion = "2.0" ProjectGuid = "{0FCA7883-C7B0-4C8A-A609-40B768659FE4}" > <Build> <Settings ApplicationIcon = "" AssemblyKeyContainerName = "" AssemblyName = "AF_Firebird" AssemblyOriginatorKeyFile = "" AssemblyOriginatorKeyMode = "None" DefaultClientScript = "JScript" DefaultHTMLPageLayout = "Grid" DefaultTargetSchema = "IE50" DelaySign = "false" OutputType = "Library" OptionCompare = "Binary" OptionExplicit = "On" OptionStrict = "Off" RootNamespace = "AF_Firebird" StartupObject = "" > <Config Name = "Debug" BaseAddress = "285212672" ConfigurationOverrideFile = "" DefineConstants = "" DefineDebug = "true" DefineTrace = "true" DebugSymbols = "true" IncrementalBuild = "true" Optimize = "false" OutputPath = "bin\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "1" /> <Config Name = "Release" BaseAddress = "285212672" ConfigurationOverrideFile = "" DefineConstants = "" DefineDebug = "false" DefineTrace = "true" DebugSymbols = "false" IncrementalBuild = "false" Optimize = "true" OutputPath = "bin\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "1" /> </Settings> <References> <Reference Name = "System" AssemblyName = "System" /> <Reference Name = "System.Data" AssemblyName = "System.Data" /> <Reference Name = "System.XML" AssemblyName = "System.Xml" /> <Reference Name = "AToMSFramework" Project = "{8FFD05CF-E733-4D8E-BC0E-D9DD37B87384}" Package = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}" /> <Reference Name = "FirebirdSql.Data.Firebird" AssemblyName = "FirebirdSql.Data.Firebird" HintPath = "..\..\..\..\..\Program Files\FirebirdNETProvider1.7\FirebirdSql.Data.Firebird.dll" AssemblyFolderKey = "hklm\dn\firebirdsql.data.firebird" /> </References> <Imports> <Import Namespace = "Microsoft.VisualBasic" /> <Import Namespace = "System" /> <Import Namespace = "System.Collections" /> <Import Namespace = "System.Data" /> <Import Namespace = "System.Diagnostics" /> </Imports> </Build> <Files> <Include> <File RelPath = "AssemblyInfo.vb" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CFirebirdConnection.vb" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CFirebirdDatabase.vb" SubType = "Code" BuildAction = "Compile" /> </Include> </Files> </VisualBasic> </VisualStudioProject> --- NEW FILE: CFirebirdConnection.vb --- Imports FirebirdSql.Data.Firebird Imports AToMSFramework '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CMSSqlConnection ''' '''----------------------------------------------------------------------------- ''' <summary> ''' Connection class for MSSql data sources ''' </summary> ''' <remarks><para>This class implements the <see cref="T:AToMSFramework._CConnection"/> interface and is used ''' to manage connections to MSSQL datasources.</para> ''' <para>The following should be taken into consideration when using this ''' class:</para> ''' <para>1. Only one physical transaction runs on a database connection at any one time</para> ''' <para>2. Only one physical connection to the database exists. Multiple connection ''' objects will share a connection where possible</para> ''' <para>3. If nested transactions are started, the commit or rollback only occurs on the ''' first transaction created. A rollback on any nested transaction will cause all ''' outside transactions to also roll back.</para> ''' </remarks> ''' <seealso cref="T:AToMSFramework._CConnection"/> ''' <history> ''' [rbanks] 18/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Class CFirebirdConnection Implements _CConnection Implements IDisposable '************************************************** 'Class: CMSSqlConnection 'Author: Richard Banks '************************************************** Private m_connection As FbConnection Private m_autoCommit As Boolean Private m_started As Boolean Private m_manageTransactions As Boolean Private m_transaction As FbTransaction Private m_transactioncalls As Integer Private m_references As Integer Private m_db As _CRelationalDatabase Private Const DEBUG_MODE As Boolean = True Private m_disposed As Boolean '''----------------------------------------------------------------------------- ''' <summary> ''' The actual SQL Server connection for the object. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property Connection() As FbConnection Get Connection = m_connection End Get Set(ByVal Value As FbConnection) m_connection = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.AutoCommit">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property AutoCommit() As Boolean Implements _CConnection.AutoCommit Get AutoCommit = m_autoCommit End Get Set(ByVal Value As Boolean) m_autoCommit = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.Started">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property Started() As Boolean Implements _CConnection.Started Get Started = m_started End Get Set(ByVal Value As Boolean) m_started = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.ManageTransactions">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property ManageTransactions() As Boolean Implements _CConnection.ManageTransactions Get ManageTransactions = m_manageTransactions End Get Set(ByVal Value As Boolean) m_manageTransactions = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.commit">_CConnection</see>. ''' </summary> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub commit() Implements _CConnection.commit If DEBUG_MODE Then If m_transactioncalls = 1 Then System.Diagnostics.Debug.WriteLine("COMMIT TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested COMMIT TRANSACTION - not actually called") End If End If If Me.ManageTransactions Then If m_transactioncalls = 1 Then m_transaction.Commit() getPersistenceBrokerInstance().commitCache(Me.Database) Me.Started = False m_transaction = Nothing End If m_transactioncalls -= 1 End If End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' The current transaction for the connection. ''' </summary> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public ReadOnly Property Transaction() As FbTransaction Get Transaction = m_transaction End Get End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.startTransaction">_CConnection</see>. ''' </summary> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overloads Sub startTransaction() Implements _CConnection.startTransaction If DEBUG_MODE Then If m_transactioncalls = 0 Then System.Diagnostics.Debug.WriteLine("BEGIN TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested BEGIN TRANSACTION - not actually called") End If End If If Me.ManageTransactions Then If Not Me.Started Then m_transaction = m_connection.BeginTransaction getPersistenceBrokerInstance().startCacheTransaction(Me.Database) End If m_transactioncalls += 1 Me.Started = True End If End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.processStatement">_CConnection</see>. ''' </summary> ''' <param name="statement"></param> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' [rbanks] 23/01/2004 Changed to use SQL parameters ''' </history> '''----------------------------------------------------------------------------- Public Sub processStatement(ByVal statement As CSqlStatement) Implements _CConnection.processStatement Dim m_command As New FbCommand Dim m_recordcount As Integer Dim cp As CSQLParameter Dim param As FbParameter Dim dd As Date Try m_command.Connection = m_connection m_command.CommandText = statement.SqlString For Each cp In statement.Parameters If Not cp.Ignore Then param = New FbParameter param.ParameterName = cp.Name param.FbDbType = CType(cp.Column.ProviderType, FbDbType) param.Value = cp.Value m_command.Parameters.Add(param) End If Next m_command.Transaction = m_transaction Debug.WriteLine(m_command.CommandText) m_recordcount = m_command.ExecuteNonQuery() If m_recordcount = 0 Then Throw New NothingUpdatedException("No records were affected by the update") End If Catch err As FbException Throw err Catch err As Exception Throw err End Try End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.processSelectStatement">_CConnection</see>. ''' </summary> ''' <param name="statement"></param> ''' <returns></returns> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Function processSelectStatement(ByVal statement As CSqlStatement) As CResultset Implements _CConnection.processSelectStatement SyncLock GetType(CFirebirdConnection) Dim x As RetrieveException Dim rs As New CResultset Dim param As FbParameter Dim dd As Date Dim m_command As New FbCommand If DEBUG_MODE Then System.Diagnostics.Debug.WriteLine(statement.SqlString) End If m_command.Connection = m_connection m_command.CommandText = statement.SqlString For Each cp As CSQLParameter In statement.Parameters If Not cp.Ignore Then param = New FbParameter param.ParameterName = cp.Name param.FbDbType = CType(cp.Column.ProviderType, FbDbType) param.Value = cp.Value m_command.Parameters.Add(param) End If Next Try Dim m_adapter As New FbDataAdapter(m_command) If m_transactioncalls > 0 Then m_adapter.SelectCommand.Transaction = m_transaction m_adapter.Fill(rs.ResultSet, "ole") m_adapter.Dispose() Catch err As FbException x = New RetrieveException("SQL Error: " & err.Message, err) Catch err As Exception x = New RetrieveException(err.Message, err) End Try If Not x Is Nothing Then Throw x End If processSelectStatement = rs End SyncLock End Function '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.rollback">_CConnection</see>. ''' </summary> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub rollback() Implements _CConnection.rollback Dim pb As CPersistenceBroker If DEBUG_MODE Then If m_transactioncalls = 1 Then System.Diagnostics.Debug.WriteLine("ROLLBACK TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested ROLLBACK TRANSACTION - not actually performed") End If End If If Me.ManageTransactions Then If m_transactioncalls = 1 Then Try m_transaction.Rollback() Catch ex As Exception End Try getPersistenceBrokerInstance().rollbackCache(Me.Database) Me.Started = False m_transaction = Nothing End If m_transactioncalls -= 1 End If End Sub Public Sub New() MyBase.New() 'By default we manage tranactions 'For DB's that do not manage transactions we should 'set this attribute to false m_manageTransactions = True m_references = 0 End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.CloseConnection">_CConnection</see>. ''' </summary> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub CloseConnection() Implements _CConnection.CloseConnection m_references -= 1 If m_references = 0 Then m_connection.Close() End If End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.IsClosed">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public ReadOnly Property IsClosed() As Boolean Implements _CConnection.IsClosed Get Return m_connection.State = ConnectionState.Closed End Get End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.ReferenceCount">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property ReferenceCount() As Integer Implements _CConnection.ReferenceCount Get Return m_references End Get Set(ByVal Value As Integer) m_references = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.getTableSchema">_CConnection</see>. ''' </summary> ''' <param name="tName"></param> ''' <returns></returns> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Function getTableSchema(ByVal tName As String) As System.Data.DataTable Implements _CConnection.getTableSchema Dim statement As String Dim cmd As FbCommand Dim dr As FbDataReader Dim dt As DataTable statement = "select * from " & tName Try cmd = New FbCommand(statement, Me.Connection) dr = cmd.ExecuteReader(CommandBehavior.SchemaOnly) dt = dr.GetSchemaTable Catch ex As Exception dt = Nothing Throw ex End Try Return dt End Function Public Overloads Sub startTransaction(ByVal isolationLevel As System.Data.IsolationLevel) Implements _CConnection.startTransaction If DEBUG_MODE Then If m_transactioncalls = 0 Then System.Diagnostics.Debug.WriteLine("BEGIN TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested BEGIN TRANSACTION - not actually called") End If End If If Me.ManageTransactions Then If Not Me.Started Then m_transaction = m_connection.BeginTransaction(isolationLevel) getPersistenceBrokerInstance().startCacheTransaction(Me.Database) End If m_transactioncalls += 1 Me.Started = True End If End Sub Public Property Database() As _CRelationalDatabase Implements _CConnection.Database Get Return m_db End Get Set(ByVal Value As _CRelationalDatabase) m_db = Value End Set End Property Public Overloads Sub Dispose() Implements System.IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) If Not m_disposed Then If disposing Then If Me.Started AndAlso Not m_transaction Is Nothing Then m_transaction.Rollback() m_transaction = Nothing End If If Not m_connection Is Nothing Then m_connection.Close() m_connection.Dispose() m_connection = Nothing End If m_db = Nothing m_disposed = True End If End If End Sub Protected Overrides Sub Finalize() ' Simply call Dispose(False). Dispose(False) End Sub End Class --- NEW FILE: AssemblyInfo.vb --- Imports System Imports System.Reflection Imports System.Runtime.InteropServices ' General Information about an assembly is controlled through the following ' set of attributes. Change these attribute values to modify the information ' associated with an assembly. ' Review the values of the assembly attributes <Assembly: AssemblyTitle("")> <Assembly: AssemblyDescription("")> <Assembly: AssemblyCompany("")> <Assembly: AssemblyProduct("")> <Assembly: AssemblyCopyright("")> <Assembly: AssemblyTrademark("")> <Assembly: CLSCompliant(True)> 'The following GUID is for the ID of the typelib if this project is exposed to COM <Assembly: Guid("6DE6B2EC-4285-42A2-8E61-14147FE3263D")> ' Version information for an assembly consists of the following four values: ' ' Major Version ' Minor Version ' Build Number ' Revision ' ' You can specify all the values or you can default the Build and Revision Numbers ' by using the '*' as shown below: <Assembly: AssemblyVersion("1.0.*")> |
From: Richard B. <rb...@us...> - 2005-02-07 23:29:59
|
Update of /cvsroot/jcframework/dotnet In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24084 Modified Files: AToMSFramework.sln Log Message: Added initial Firebird support (usng 1.7 RC1 .net provider) Index: AToMSFramework.sln =================================================================== RCS file: /cvsroot/jcframework/dotnet/AToMSFramework.sln,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- AToMSFramework.sln 7 Feb 2005 07:37:35 -0000 1.3 +++ AToMSFramework.sln 7 Feb 2005 23:29:48 -0000 1.4 @@ -31,6 +31,14 @@ ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AF_Firebird", "Providers\AF_Firebird\AF_Firebird.vbproj", "{0FCA7883-C7B0-4C8A-A609-40B768659FE4}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AF_PostgreSQL", "Providers\AF_PostgreSQL\AF_PostgreSQL.vbproj", "{5B36A25D-53F1-4AD2-8A79-9BA9AA0E43B0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(DPCodeReviewSolutionGUID) = preSolution DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000} @@ -72,6 +80,14 @@ {09659A30-0220-42BF-9478-267278E89692}.Debug.Build.0 = Debug|.NET {09659A30-0220-42BF-9478-267278E89692}.Release.ActiveCfg = Release|.NET {09659A30-0220-42BF-9478-267278E89692}.Release.Build.0 = Release|.NET + {0FCA7883-C7B0-4C8A-A609-40B768659FE4}.Debug.ActiveCfg = Debug|.NET + {0FCA7883-C7B0-4C8A-A609-40B768659FE4}.Debug.Build.0 = Debug|.NET + {0FCA7883-C7B0-4C8A-A609-40B768659FE4}.Release.ActiveCfg = Release|.NET + {0FCA7883-C7B0-4C8A-A609-40B768659FE4}.Release.Build.0 = Release|.NET + {5B36A25D-53F1-4AD2-8A79-9BA9AA0E43B0}.Debug.ActiveCfg = Debug|.NET + {5B36A25D-53F1-4AD2-8A79-9BA9AA0E43B0}.Debug.Build.0 = Debug|.NET + {5B36A25D-53F1-4AD2-8A79-9BA9AA0E43B0}.Release.ActiveCfg = Release|.NET + {5B36A25D-53F1-4AD2-8A79-9BA9AA0E43B0}.Release.Build.0 = Release|.NET EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection |
From: Richard B. <rb...@us...> - 2005-02-07 23:27:57
|
Update of /cvsroot/jcframework/dotnet/Providers/AF_Firebird In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23411/AF_Firebird Log Message: Directory /cvsroot/jcframework/dotnet/Providers/AF_Firebird added to the repository |
From: Richard B. <rb...@us...> - 2005-02-07 23:09:42
|
Update of /cvsroot/jcframework/dotnet/Providers/AF_PostgreSQL In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17806/Providers/AF_PostgreSQL Added Files: AF_PostgreSQL.vbproj AssemblyInfo.vb CPostgreSQLConnection.vb CPostgreSQLDatabase.vb Log Message: Added PotsgreSQL provider --- NEW FILE: AssemblyInfo.vb --- Imports System Imports System.Reflection Imports System.Runtime.InteropServices ' General Information about an assembly is controlled through the following ' set of attributes. Change these attribute values to modify the information ' associated with an assembly. ' Review the values of the assembly attributes <Assembly: AssemblyTitle("")> <Assembly: AssemblyDescription("")> <Assembly: AssemblyCompany("")> <Assembly: AssemblyProduct("")> <Assembly: AssemblyCopyright("")> <Assembly: AssemblyTrademark("")> <Assembly: CLSCompliant(True)> 'The following GUID is for the ID of the typelib if this project is exposed to COM <Assembly: Guid("3270AB19-71DE-4AF8-9627-6CC3A6DC6627")> ' Version information for an assembly consists of the following four values: ' ' Major Version ' Minor Version ' Build Number ' Revision ' ' You can specify all the values or you can default the Build and Revision Numbers ' by using the '*' as shown below: <Assembly: AssemblyVersion("1.0.*")> --- NEW FILE: CPostgreSQLDatabase.vb --- Option Strict Off Option Explicit On Imports Npgsql Imports AToMSFramework '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CPostgreSQLDatabase ''' '''----------------------------------------------------------------------------- ''' <summary> ''' Implementation of CRelationalDatabase for Postgres SQL Servers. ''' </summary> ''' <remarks>This class contains the specific functionality required for the ''' framework to interact with PostgreSQL databases.</remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Class CPostgreSQLDatabase Inherits CRelationalDatabase Private m_name As String Private m_user As String Private m_password As String Private m_serverName As String '''----------------------------------------------------------------------------- ''' <summary> ''' Establishes a new database connection. ''' </summary> ''' <returns>A CMSSqlConnection containing the newly established connection.</returns> ''' <remarks>The CMSSqlConnection class implements the _CConnection interface which ''' is required by this method. ''' <para>If the connection cannot be established an exception will be thrown.</para> ''' <para>The connection is established using normal SQL server authentication (ie ''' Integrated security is false, and persiste security info is false.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getNewConnection() As _CConnection Dim conn As New CPostgreSQLConnection conn.Connection = New NpgsqlConnection conn.ManageTransactions = True Try If m_user Is Nothing OrElse m_user.Length = 0 Then m_user = "" m_password = "" Dim pbroker As CPersistenceBroker pbroker = getPersistenceBrokerInstance() pbroker.GetLoginDetails(Me, m_user, m_password) End If conn.Connection.ConnectionString = _ "Data Source=" & m_serverName & ";" & _ "Initial Catalog=" & m_name & ";" & _ "Integrated Security=false;" & _ "Persist Security Info=False;" & _ "User Id=" & m_user & ";" & _ "Password=" & m_password conn.Connection.Open() Catch ex As NpgsqlException Throw New DatabaseConnectionException(ex.Message, ex) Catch ex As Exception Throw New DatabaseConnectionException(ex.Message, ex) End Try getNewConnection = conn End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Sets the initial properties of the database. ''' </summary> ''' <param name="properties">The property information supplied in the XML mapping file.</param> ''' <remarks>In order to initialise the database object properly the following must be supplied ''' <list type="bullet"> ''' <item><description>Name: The name of the database on the server (ie the catalog name)</description></item> ''' <item><description>ServerName: The name of the database server</description></item> ''' <item><description>User: The user name for secured databases.</description></item> ''' <item><description>Password: The password for secured databases.</description></item> ''' <item><description>OIDTable: The table name containing the OID A-value. Can be ignored if OIDs are not used.</description></item> ''' </list> ''' <para>If the database is used without having been properly initialised you are likely ''' to get exceptions thrown in your application.</para> ''' </remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Sub init(ByVal properties As System.Collections.Specialized.HybridDictionary) m_name = properties.Item("name") m_serverName = properties.Item("serverName") m_user = properties.Item("user") m_password = properties.Item("password") If properties.Item("ansinulls") Is Nothing Then UseANSINulls = False Else UseANSINulls = properties.Item("ansinulls") End If MyBase.OIDTable = properties.Item("OIDTable") End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' Gets the value of an object in a format the database can understand. ''' </summary> ''' <param name="tempValue">The object being evaluated.</param> ''' <returns>A string containing the SQL compatible value for the object</returns> ''' <remarks>The following rules are applied when converting object values into ''' database compatible strings ''' <para>Any value that is a Null Alias <see cref="M:AToMSFramework.ModAliasNull.IsNullAlias"/> ''' will be returned as NULL.</para> ''' <para>Strings are enclosed in single quotes. If the string is already enclosed in single quotes then ''' nothing is changed. Also, any single quotes within the string are converted to a pair of single quotes.</para> ''' <para>Dates are converted to yyyy-MM-dd HH:mm:ss format and enclosed in single quotes. If a datetime field ''' only has a time value, then a time-only string is returned instead.</para> ''' <para>Booleans are converted to 1 or 0</para> ''' <para>Numbers are converted to strings directly.</para> ''' <para>Objects that are nothing return a NULL and all other objects are directly converted to strings using their ''' inbuilt ToString methods.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getValueFor(ByVal tempValue As Object) As String Dim tempRetorno As String Dim dd As DateTime Dim OriginalCulture As System.Globalization.CultureInfo Dim TempCulture As System.Globalization.CultureInfo If IsNullAlias(tempValue) Then Return "NULL" Else Select Case VarType(tempValue) Case VariantType.String If Left(tempValue, 1) = "'" And Right(tempValue, 1) = "'" And CStr(tempValue).Length > 2 Then 'string already enclosed in quotes so ignore tempRetorno = tempValue Else 'replace single quote with double quote, and enclose entire string in quotes tempRetorno = "'" & Replace(tempValue, "'", "''") & "'" End If Case VariantType.Date TempCulture = New System.Globalization.CultureInfo("en-US") OriginalCulture = System.Threading.Thread.CurrentThread.CurrentCulture System.Threading.Thread.CurrentThread.CurrentCulture = TempCulture System.Threading.Thread.CurrentThread.CurrentUICulture = TempCulture dd = CType(tempValue, DateTime) If dd = Date.MinValue Then tempRetorno = "NULL" Else If dd.Date.Ticks = 0 Then 'MSSQL doesn't support dates with years less than 1753, so time only 'values that format to "0001-01-01 11:23:00" for example produce errors. 'If it's just a time we will only return time portion. tempRetorno = "'" & dd.ToString("HH:mm:ss") & "'" Else tempRetorno = "'" & dd.ToString("yyyy-MM-dd HH:mm:ss") & "'" End If End If System.Threading.Thread.CurrentThread.CurrentCulture = OriginalCulture System.Threading.Thread.CurrentThread.CurrentUICulture = OriginalCulture Case VariantType.Boolean tempRetorno = IIf(tempValue, "1", "0") Case VariantType.Single, VariantType.Double, VariantType.Decimal, VariantType.Decimal tempRetorno = tempValue.ToString Case Else tempRetorno = tempValue End Select End If getValueFor = tempRetorno End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Gets the next OID A-Value from the database. ''' </summary> ''' <returns>A integer containing the A-Value.</returns> ''' <remarks>A connection is established to the database and the OIDTable (specified in ''' the XML mapping) is queried and updated. The obtained A-Value is returned. ''' <para>Should an error occur a value of 0 will be returned.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getNextOIDAvalue() As Integer Dim rs As New DataSet Dim da As New NpgsqlDataAdapter Dim cb As NpgsqlCommandBuilder Dim aValue As Integer Dim row As System.Data.DataRow Dim p As NpgsqlParameter Dim initvals() As Object = {1} Dim x As OIDException Dim conn As CPostgreSQLConnection conn = Me.getConnection(Nothing) conn.AutoCommit = False conn.startTransaction() Try da.SelectCommand = New NpgsqlCommand("select oidAValue from " & Me.OIDTable, conn.Connection, conn.Transaction) cb = New NpgsqlCommandBuilder(da) da.Fill(rs, "oid") If rs.Tables(0).Rows.Count = 0 Then 'Seed with value = 1 row = rs.Tables(0).Rows.Add(initvals) aValue = 1 Else rs.Tables(0).Rows(0).Item(0) += 1 aValue = rs.Tables(0).Rows(0).Item(0) End If da.Update(rs, "oid") da.Dispose() conn.commit() Catch err As NpgsqlException conn.rollback() x = New OIDException(err.Message, err) Catch err As Exception conn.rollback() x = New OIDException(err.Message, err) Finally Me.freeConnection(conn) If Not x Is Nothing Then Throw x End If End Try Return aValue End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Method to get the last Identity value for the connection. ''' </summary> ''' <param name="conn">The connection to use.</param> ''' <returns>An integer containing the value of the last updated identity column</returns> ''' <remarks>If multiple identity columns were updated the return value will only contain ''' the value of the last identity column updated. ''' <para>Identity values are retrieved by querying the @@IDENTITY value.</para> ''' <para>Should an error occur an exception will be thrown.</para></remarks> ''' <history> ''' [rbanks] 11/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getIdentityValue(ByVal conn As _CConnection) As Integer Dim rs As New DataSet Dim da As New NpgsqlDataAdapter Dim cb As NpgsqlCommandBuilder Dim aValue As Integer Dim connection As CPostgreSQLConnection connection = conn connection.AutoCommit = False Try da.SelectCommand = New NpgsqlCommand("select @@IDENTITY", connection.Connection, connection.Transaction) cb = New NpgsqlCommandBuilder(da) da.Fill(rs, "identity") If rs.Tables(0).Rows.Count = 0 Then Throw New IdentityValueException("Could not retrieve identity value") Else If IsDBNull(rs.Tables(0).Rows(0).Item(0)) Then aValue = 0 Else aValue = rs.Tables(0).Rows(0).Item(0) End If Debug.WriteLine("Returned Identity value: " & aValue.ToString) End If da.Dispose() Catch err As NpgsqlException Throw New IdentityValueException(err.Message, err) End Try Return aValue End Function '''----------------------------------------------------------------------------- ''' <summary> ''' Returns the SQL syntax placeholder for a parameter ''' </summary> ''' <param name="i">The number of the parameter being added</param> ''' <returns>A string containing the SQL parameter placeholder</returns> ''' <remarks>Since the parameter is for an MSSQL connection only a the returned ''' string is in the format of @pxxx where xxx is the value of the input integer (i).</remarks> ''' <history> ''' [rbanks] 23/01/2004 Created ''' </history> '''----------------------------------------------------------------------------- Public Overrides Function getParamHolder(ByVal i As Integer) As String Return "@p" & CStr(i) End Function Public Overrides Function limitClauseAtStart() As Boolean Return True End Function Public Overrides Function getClauseStringLimit() As String Return "TOP" End Function Public Overrides Function getClauseStringTableAlias(ByVal table As String, ByVal owner As String, ByVal pAlias As String) As String Return Me.m_name & "." & owner & "." & table & " as " & pAlias End Function Public Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If Not m_disposed Then If disposing Then Dim conn As CPostgreSQLConnection While ConnectionPool.Count > 0 conn = ConnectionPool.Pop conn.Dispose() End While m_disposed = True End If End If End Sub End Class --- NEW FILE: CPostgreSQLConnection.vb --- Imports Npgsql Imports AToMSFramework '''----------------------------------------------------------------------------- ''' Project : AToMSFramework ''' Class : CMSSqlConnection ''' '''----------------------------------------------------------------------------- ''' <summary> ''' Connection class for MSSql data sources ''' </summary> ''' <remarks><para>This class implements the <see cref="T:AToMSFramework._CConnection"/> interface and is used ''' to manage connections to MSSQL datasources.</para> ''' <para>The following should be taken into consideration when using this ''' class:</para> ''' <para>1. Only one physical transaction runs on a database connection at any one time</para> ''' <para>2. Only one physical connection to the database exists. Multiple connection ''' objects will share a connection where possible</para> ''' <para>3. If nested transactions are started, the commit or rollback only occurs on the ''' first transaction created. A rollback on any nested transaction will cause all ''' outside transactions to also roll back.</para> ''' </remarks> ''' <seealso cref="T:AToMSFramework._CConnection"/> ''' <history> ''' [rbanks] 18/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Class CPostgreSQLConnection Implements _CConnection Implements IDisposable '************************************************** 'Class: CMSSqlConnection 'Author: Richard Banks '************************************************** Private m_connection As NpgsqlConnection Private m_autoCommit As Boolean Private m_started As Boolean Private m_manageTransactions As Boolean Private m_transaction As NpgsqlTransaction Private m_transactioncalls As Integer Private m_references As Integer Private m_db As _CRelationalDatabase Private Const DEBUG_MODE As Boolean = True Private m_disposed As Boolean '''----------------------------------------------------------------------------- ''' <summary> ''' The actual SQL Server connection for the object. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property Connection() As NpgsqlConnection Get Connection = m_connection End Get Set(ByVal Value As NpgsqlConnection) m_connection = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.AutoCommit">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property AutoCommit() As Boolean Implements _CConnection.AutoCommit Get AutoCommit = m_autoCommit End Get Set(ByVal Value As Boolean) m_autoCommit = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.Started">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property Started() As Boolean Implements _CConnection.Started Get Started = m_started End Get Set(ByVal Value As Boolean) m_started = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.ManageTransactions">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property ManageTransactions() As Boolean Implements _CConnection.ManageTransactions Get ManageTransactions = m_manageTransactions End Get Set(ByVal Value As Boolean) m_manageTransactions = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.commit">_CConnection</see>. ''' </summary> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub commit() Implements _CConnection.commit If DEBUG_MODE Then If m_transactioncalls = 1 Then System.Diagnostics.Debug.WriteLine("COMMIT TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested COMMIT TRANSACTION - not actually called") End If End If If Me.ManageTransactions Then If m_transactioncalls = 1 Then m_transaction.Commit() getPersistenceBrokerInstance().commitCache(Me.Database) Me.Started = False m_transaction = Nothing End If m_transactioncalls -= 1 End If End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' The current transaction for the connection. ''' </summary> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public ReadOnly Property Transaction() As NpgsqlTransaction Get Transaction = m_transaction End Get End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.startTransaction">_CConnection</see>. ''' </summary> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Overloads Sub startTransaction() Implements _CConnection.startTransaction If DEBUG_MODE Then If m_transactioncalls = 0 Then System.Diagnostics.Debug.WriteLine("BEGIN TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested BEGIN TRANSACTION - not actually called") End If End If If Me.ManageTransactions Then If Not Me.Started Then m_transaction = m_connection.BeginTransaction getPersistenceBrokerInstance().startCacheTransaction(Me.Database) End If m_transactioncalls += 1 Me.Started = True End If End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.processStatement">_CConnection</see>. ''' </summary> ''' <param name="statement"></param> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' [rbanks] 23/01/2004 Changed to use SQL parameters ''' </history> '''----------------------------------------------------------------------------- Public Sub processStatement(ByVal statement As CSqlStatement) Implements _CConnection.processStatement Dim m_command As New NpgsqlCommand Dim m_recordcount As Integer Dim cp As CSQLParameter Dim param As NpgsqlParameter Dim dd As Date Try m_command.Connection = m_connection m_command.CommandText = statement.SqlString For Each cp In statement.Parameters If Not cp.Ignore Then param = New NpgsqlParameter param.ParameterName = cp.Name param.NpgsqlDbType = CType(cp.Column.ProviderType, NpgsqlTypes.NpgsqlDbType) param.Value = cp.Value m_command.Parameters.Add(param) End If Next m_command.Transaction = m_transaction Debug.WriteLine(m_command.CommandText) m_recordcount = m_command.ExecuteNonQuery() If m_recordcount = 0 Then Throw New NothingUpdatedException("No records were affected by the update") End If Catch err As NpgsqlException Throw err Catch err As Exception Throw err End Try End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.processSelectStatement">_CConnection</see>. ''' </summary> ''' <param name="statement"></param> ''' <returns></returns> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Function processSelectStatement(ByVal statement As CSqlStatement) As CResultset Implements _CConnection.processSelectStatement SyncLock GetType(CPostgreSQLConnection) Dim x As RetrieveException Dim rs As New CResultset Dim param As NpgsqlParameter Dim dd As Date Dim m_command As New NpgsqlCommand If DEBUG_MODE Then System.Diagnostics.Debug.WriteLine(statement.SqlString) End If m_command.Connection = m_connection m_command.CommandText = statement.SqlString For Each cp As CSQLParameter In statement.Parameters If Not cp.Ignore Then param = New NpgsqlParameter param.ParameterName = cp.Name param.NpgsqlDbType = CType(cp.Column.ProviderType, NpgsqlTypes.NpgsqlDbType) param.Value = cp.Value m_command.Parameters.Add(param) End If Next Try Dim m_adapter As New NpgsqlDataAdapter(m_command) If m_transactioncalls > 0 Then m_adapter.SelectCommand.Transaction = m_transaction m_adapter.Fill(rs.ResultSet, "ole") m_adapter.Dispose() Catch err As NpgsqlException x = New RetrieveException("SQL Error: " & err.Message, err) Catch err As Exception x = New RetrieveException(err.Message, err) End Try If Not x Is Nothing Then Throw x End If processSelectStatement = rs End SyncLock End Function '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.rollback">_CConnection</see>. ''' </summary> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub rollback() Implements _CConnection.rollback Dim pb As CPersistenceBroker If DEBUG_MODE Then If m_transactioncalls = 1 Then System.Diagnostics.Debug.WriteLine("ROLLBACK TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested ROLLBACK TRANSACTION - not actually performed") End If End If If Me.ManageTransactions Then If m_transactioncalls = 1 Then Try m_transaction.Rollback() Catch ex As Exception End Try getPersistenceBrokerInstance().rollbackCache(Me.Database) Me.Started = False m_transaction = Nothing End If m_transactioncalls -= 1 End If End Sub Public Sub New() MyBase.New() 'By default we manage tranactions 'For DB's that do not manage transactions we should 'set this attribute to false m_manageTransactions = True m_references = 0 End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="M:AToMSFramework._CConnection.CloseConnection">_CConnection</see>. ''' </summary> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Sub CloseConnection() Implements _CConnection.CloseConnection m_references -= 1 If m_references = 0 Then m_connection.Close() End If End Sub '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.IsClosed">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public ReadOnly Property IsClosed() As Boolean Implements _CConnection.IsClosed Get Return m_connection.State = ConnectionState.Closed End Get End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.ReferenceCount">_CConnection</see>. ''' </summary> ''' <value></value> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Property ReferenceCount() As Integer Implements _CConnection.ReferenceCount Get Return m_references End Get Set(ByVal Value As Integer) m_references = Value End Set End Property '''----------------------------------------------------------------------------- ''' <summary> ''' See <see cref="P:AToMSFramework._CConnection.getTableSchema">_CConnection</see>. ''' </summary> ''' <param name="tName"></param> ''' <returns></returns> ''' <remarks></remarks> ''' <history> ''' [rbanks] 1/12/2003 Created ''' </history> '''----------------------------------------------------------------------------- Public Function getTableSchema(ByVal tName As String) As System.Data.DataTable Implements _CConnection.getTableSchema Dim statement As String Dim cmd As NpgsqlCommand Dim dr As NpgsqlDataReader Dim dt As DataTable statement = "select * from " & tName Try cmd = New NpgsqlCommand(statement, Me.Connection) dr = cmd.ExecuteReader(CommandBehavior.SchemaOnly) dt = dr.GetSchemaTable Catch ex As Exception dt = Nothing Throw ex End Try Return dt End Function Public Overloads Sub startTransaction(ByVal isolationLevel As System.Data.IsolationLevel) Implements _CConnection.startTransaction If DEBUG_MODE Then If m_transactioncalls = 0 Then System.Diagnostics.Debug.WriteLine("BEGIN TRANSACTION") Else System.Diagnostics.Debug.WriteLine("Nested BEGIN TRANSACTION - not actually called") End If End If If Me.ManageTransactions Then If Not Me.Started Then m_transaction = m_connection.BeginTransaction(isolationLevel) getPersistenceBrokerInstance().startCacheTransaction(Me.Database) End If m_transactioncalls += 1 Me.Started = True End If End Sub Public Property Database() As _CRelationalDatabase Implements _CConnection.Database Get Return m_db End Get Set(ByVal Value As _CRelationalDatabase) m_db = Value End Set End Property Public Overloads Sub Dispose() Implements System.IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) If Not m_disposed Then If disposing Then If Me.Started AndAlso Not m_transaction Is Nothing Then m_transaction.Rollback() m_transaction = Nothing End If If Not m_connection Is Nothing Then m_connection.Close() m_connection.Dispose() m_connection = Nothing End If m_db = Nothing m_disposed = True End If End If End Sub Protected Overrides Sub Finalize() ' Simply call Dispose(False). Dispose(False) End Sub End Class --- NEW FILE: AF_PostgreSQL.vbproj --- <VisualStudioProject> <VisualBasic ProjectType = "Local" ProductVersion = "7.10.3077" SchemaVersion = "2.0" ProjectGuid = "{5B36A25D-53F1-4AD2-8A79-9BA9AA0E43B0}" > <Build> <Settings ApplicationIcon = "" AssemblyKeyContainerName = "" AssemblyName = "AF_PostgreSQL" AssemblyOriginatorKeyFile = "" AssemblyOriginatorKeyMode = "None" DefaultClientScript = "JScript" DefaultHTMLPageLayout = "Grid" DefaultTargetSchema = "IE50" DelaySign = "false" OutputType = "Library" OptionCompare = "Binary" OptionExplicit = "On" OptionStrict = "Off" RootNamespace = "AF_PostgreSQL" StartupObject = "" > <Config Name = "Debug" BaseAddress = "285212672" ConfigurationOverrideFile = "" DefineConstants = "" DefineDebug = "true" DefineTrace = "true" DebugSymbols = "true" IncrementalBuild = "true" Optimize = "false" OutputPath = "bin\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "1" /> <Config Name = "Release" BaseAddress = "285212672" ConfigurationOverrideFile = "" DefineConstants = "" DefineDebug = "false" DefineTrace = "true" DebugSymbols = "false" IncrementalBuild = "false" Optimize = "true" OutputPath = "bin\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "1" /> </Settings> <References> <Reference Name = "System" AssemblyName = "System" /> <Reference Name = "System.Data" AssemblyName = "System.Data" /> <Reference Name = "System.XML" AssemblyName = "System.Xml" /> <Reference Name = "AToMSFramework" Project = "{8FFD05CF-E733-4D8E-BC0E-D9DD37B87384}" Package = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}" /> <Reference Name = "Npgsql" AssemblyName = "Npgsql" HintPath = "..\..\..\..\misc\Npgsql\bin\ms\Npgsql.dll" /> </References> <Imports> <Import Namespace = "Microsoft.VisualBasic" /> <Import Namespace = "System" /> <Import Namespace = "System.Collections" /> <Import Namespace = "System.Data" /> <Import Namespace = "System.Diagnostics" /> </Imports> </Build> <Files> <Include> <File RelPath = "AssemblyInfo.vb" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CPostgreSQLConnection.vb" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CPostgreSQLDatabase.vb" SubType = "Code" BuildAction = "Compile" /> </Include> </Files> </VisualBasic> </VisualStudioProject> |
From: Richard B. <rb...@us...> - 2005-02-07 23:08:54
|
Update of /cvsroot/jcframework/dotnet/Providers/AF_PostgreSQL In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17685/AF_PostgreSQL Log Message: Directory /cvsroot/jcframework/dotnet/Providers/AF_PostgreSQL added to the repository |
From: Richard B. <rb...@us...> - 2005-02-07 22:07:54
|
Update of /cvsroot/jcframework/Nunit In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28478 Modified Files: AtomsFramework.xml Log Message: Extra unit test for collections and transaction rollbacks Also change to XML file to use providers instead of classes Index: AtomsFramework.xml =================================================================== RCS file: /cvsroot/jcframework/Nunit/AtomsFramework.xml,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- AtomsFramework.xml 2 Jan 2005 09:41:09 -0000 1.15 +++ AtomsFramework.xml 7 Feb 2005 22:07:15 -0000 1.16 @@ -1,6 +1,6 @@ <?xml version="1.0" ?> <map> - <database name="MSA" class="CMsAccessDatabase"> + <database name="MSA" provider="C:\Projects\MMM\Atoms_Framework\Providers\AF_OLEDB\bin\AF_OLEDB.dll"> <parameter name="name" value=".\db1.mdb" /> <parameter name="user" value="anyuser" /> <parameter name="password" value="anypassword" /> |
From: Richard B. <rb...@us...> - 2005-02-07 22:07:34
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28478/InheritedClasses Modified Files: AtomsFrameworkTests.vb Log Message: Extra unit test for collections and transaction rollbacks Also change to XML file to use providers instead of classes Index: AtomsFrameworkTests.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/AtomsFrameworkTests.vb,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- AtomsFrameworkTests.vb 6 Feb 2005 02:45:19 -0000 1.12 +++ AtomsFrameworkTests.vb 7 Feb 2005 22:07:16 -0000 1.13 @@ -485,5 +485,60 @@ Assert.IsNull(a1.TableBCollection) End Sub - End Class + <Test()> Public Sub CheckCacheAfterRollback4() + 'Add and remove items in the collection during the transaction + Dim a As New TableA + Dim b As New TableB + Dim a1 As New TableA + a.Id = "aa4" + b.Id = "bb41" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb42" + b.TableA = a + a.TableBCollection.Add(b) + a.Save() + Assert.AreEqual(2, a.TableBCollection.Count) + pbroker.startTransaction() + a1.Id = "aa4" + a1.Retrieve() + Assert.AreEqual(2, a1.TableBCollection.Count) + b = New TableB + b.Id = "bb43" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb44" + b.TableA = a + a.TableBCollection.Add(b) + b = a.TableBCollection.Item(1) + Assert.AreEqual("bb42", b.Id) + a.TableBCollection.Remove(1) + b.Delete() + Assert.AreEqual(3, a.TableBCollection.Count) + a.Save() + a1 = New TableA + a1.Id = "aa4" + a1.Retrieve() + b = New TableB + b.Id = "bb42" + b.Retrieve() + Assert.IsFalse(b.Persistent) + Assert.AreEqual(3, a1.TableBCollection.Count) + 'Now abort the transaction + pbroker.rollback() + a1 = New TableA + a1.Id = "aa4" + a1.Retrieve() + b = New TableB + b.Id = "bb42" + b.Retrieve() + Assert.IsTrue(b.Persistent) + Assert.AreEqual(2, a1.TableBCollection.Count) + Assert.AreEqual("bb42", CType(a1.TableBCollection.Item(1), TableB).Id) + End Sub + + + End Class End Namespace \ No newline at end of file |
From: Richard B. <rb...@us...> - 2005-02-07 22:06:01
|
Update of /cvsroot/jcframework/Nunit/InheritedClasses In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28092/InheritedClasses Modified Files: Tag: v2_0 AtomsFrameworkTests.vb Log Message: Extra unit test for collections and transaction rollbacks Index: AtomsFrameworkTests.vb =================================================================== RCS file: /cvsroot/jcframework/Nunit/InheritedClasses/AtomsFrameworkTests.vb,v retrieving revision 1.11.2.1 retrieving revision 1.11.2.2 diff -u -d -r1.11.2.1 -r1.11.2.2 --- AtomsFrameworkTests.vb 6 Feb 2005 02:49:52 -0000 1.11.2.1 +++ AtomsFrameworkTests.vb 7 Feb 2005 22:05:52 -0000 1.11.2.2 @@ -485,5 +485,60 @@ Assert.IsNull(a1.TableBCollection) End Sub - End Class + <Test()> Public Sub CheckCacheAfterRollback4() + 'Add and remove items in the collection during the transaction + Dim a As New TableA + Dim b As New TableB + Dim a1 As New TableA + a.Id = "aa4" + b.Id = "bb41" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb42" + b.TableA = a + a.TableBCollection.Add(b) + a.Save() + Assert.AreEqual(2, a.TableBCollection.Count) + pbroker.startTransaction() + a1.Id = "aa4" + a1.Retrieve() + Assert.AreEqual(2, a1.TableBCollection.Count) + b = New TableB + b.Id = "bb43" + b.TableA = a + a.TableBCollection.Add(b) + b = New TableB + b.Id = "bb44" + b.TableA = a + a.TableBCollection.Add(b) + b = a.TableBCollection.Item(1) + Assert.AreEqual("bb42", b.Id) + a.TableBCollection.Remove(1) + b.Delete() + Assert.AreEqual(3, a.TableBCollection.Count) + a.Save() + a1 = New TableA + a1.Id = "aa4" + a1.Retrieve() + b = New TableB + b.Id = "bb42" + b.Retrieve() + Assert.IsFalse(b.Persistent) + Assert.AreEqual(3, a1.TableBCollection.Count) + 'Now abort the transaction + pbroker.rollback() + a1 = New TableA + a1.Id = "aa4" + a1.Retrieve() + b = New TableB + b.Id = "bb42" + b.Retrieve() + Assert.IsTrue(b.Persistent) + Assert.AreEqual(2, a1.TableBCollection.Count) + Assert.AreEqual("bb42", CType(a1.TableBCollection.Item(1), TableB).Id) + End Sub + + + End Class End Namespace \ No newline at end of file |