On Jun 4, 1:50 pm, Fabio Maulo <[email protected]> wrote: > Wait... if the problem was with some proxy the issue is another (probably) > and was fixed few days ago.
I've scanned the recently fixed jira issues, and there is nothing I can see that is related to this issue. > Btw if you have a test you can create JIRA ticket > attaching the test case. Opened: http://nhjira.koah.net/browse/NH-1810 Please use the second attachment (NH1810.patch), it fits with the bug number naming convention and is a bit tidier than the original patch. > > 2009/6/4 Lee Henson <[email protected]> > > > > > > > > > Ok so: > > > - SortedSet uses SortedDictionary internally. SortedDictionary does > > not use a Hashtable internally to store it's keys and values, using > > instead a TreeBase. When the entity is inserted into a SortedSet, no > > evaluation of GetHashCode() is made. > > - HashedSet uses Hashtable internally. Hashtable will evaluate > > GetHashCode() on any object placed into it. > > > Scenario: within user code at runtime, a transient collection has a > > proxy added to it > > > - if the collection is a SortedSet, no proxy initialization takes > > place > > - if the collection is a HashedSet, the proxy is initialized and any > > onward associations (entities/collections) are added to the session > > > Scenario: during flush > > > - SortedSet: PersistentSet.GetSnapshot() is called, placing the > > contents in a Hashtable -> proxies are initialized and exception is > > thrown > > - HashedSet: PersistentSet.GetSnapshot() is called, placing the > > contents in a Hashtable -> proxies are already initialized so no > > exception is thrown > > > I think this is inconsistent. I can see two alternatives: > > > 1) if I override GetSnapshot and change the use of Hashtable to > > SortedDictionary, no exception is thrown > > > public override ICollection GetSnapshot(ICollectionPersister > > persister) > > { > > EntityMode entityMode = Session.EntityMode; > > > //if (set==null) return new Set(session); > > SortedDictionary<object, object> clonedSet = new > > SortedDictionary<object, object>(); > > foreach (object current in set) > > { > > object copied = persister.ElementType.DeepCopy(current, > > entityMode, > > persister.Factory); > > clonedSet[copied] = copied; > > } > > return clonedSet; > > } > > > However, there are obviously performance implications in using a > > SortedDictionary vs Hashtable as the size of the collection grows. > > > 2) Call GetHashCode() when an element is added to a DictionarySet: > > > public override bool Add(T o) > > { > > if (InternalDictionary.ContainsKey(o)) > > { > > return false; > > } > > else > > { > > //The object we are adding is just a placeholder. The thing > > we are > > //really concerned with is 'o', the key. > > InternalDictionary.Add(o, PlaceholderObject); > > o.GetHashCode(); > > return true; > > } > > } > > > This may modify behaviour of the applications currently using this > > class. > > > Thoughts? > > > On Jun 4, 12:07 pm, Lee Henson <[email protected]> wrote: > > > I've created a patch file for the current nh trunk, but I can't see > > > anywhere to upload it to this list. In the meantime, it is available > > > here: > > > >http://gist.github.com/123560 > > > > The patch file includes caching of GetHashCode() values as you > > > suggested, but it has no effect. The act of adding the Child in the > > > Test() method doesn't appear to trigger to a call to it's GetHashCode > > > () (which is what I presume you were expecting to fix the problem, > > > because that would happen before the flush occurred). > > > > An alternative example where this would occur is if a user writes > > > their own flush-related event handler and triggers a proxy > > > initialization. Any situation in which a proxy is initialized within > > > AbstractFlushingEventListener.PerformExecutions. Although in this > > > situation I guess you could say "just don't do that". > > > > On Jun 3, 10:49 pm, Fabio Maulo <[email protected]> wrote: > > > > > here is the problem > > > > > unchecked > > > > { > > > > return (Age*397) ^ (Parent != null ? Parent.GetHashCode() : 0);} > > > > > The hashCode can't change during instance life time especially when you > > are > > > > using it in a HashTable. > > > > private int requestedHash? > > > > public override int GetHashCode() > > > > { > > > > if(!requestedHash.HasValue) > > > > { > > > > unchecked > > > > { > > > > requestedHash = (Age*397) ^ (Parent != null ? > > Parent.GetHashCode() : > > > > 0); > > > > }} > > > > > return requestedHash; > > > > > } > > > > > 2009/6/3 Lee Henson <[email protected]> > > > > > > I have a test case that contains the following scenario: > > > > > > Parent has a custom generic set of Child which is empty > > > > > Parent has an association to a MedicalRecord > > > > > Doctor has an association to the same MedicalRecord > > > > > MedicalRecord has an set of Disease which is empty > > > > > > In a new session: > > > > > > I load the Doctor, which has the side-effect of creating a proxy of > > > > > MedicalRecord > > > > > I call a method on my Parent.Child custom collection which adds a > > > > > Child item > > > > > I save the Parent > > > > > > Within the flush machinery, my Child gets placed in a Hashtable > > > > > (PersistentSet.GetSnapshot()) which causes an evaluation of > > GetHashCode > > > > > (). Since my Child.GetHashCode has a dependency on the > > > > > Parent.GetHashCode it calls that too, and that in turn calls > > > > > MedicalRecord.GetHashCode. At this point, because MedicalRecord > > > > > already exists in the session as a proxy, it attempts to initialize > > > > > the proxy. This causes the Diseases collection to be added to the > > > > > session, and before you know it: > > > > > > AssertionFailure - collection was not processed by flush > > > > > > It might be a bit of a contrived example, but in my real model which > > > > > is a tad more complicated I am seeing this error. Rather than paste > > > > > all the code in this message, you can view the test case files/ > > > > > mappings here: > > >http://github.com/leemhenson/nhibernate/commit/4728a32efa48dc836441d3... > > > > > > There are a couple of other jira issues logged in this area for > > java's > > > > > hibernate: > > >http://opensource.atlassian.com/projects/hibernate/browse/HHH-2763;js... > > >http://opensource.atlassian.com/projects/hibernate/browse/HHH-3225;js... > > > > >http://opensource.atlassian.com/projects/hibernate/browse/HSEARCH-178 > > > > > > Thoughts? > > > > > > Cheers > > > > > Lee > > > > > -- > > > > Fabio Maulo > > -- > Fabio Maulo --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "nhusers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nhusers?hl=en -~----------~----~----~----~------~----~------~--~---
