From: <fab...@us...> - 2010-12-26 15:53:20
|
Revision: 5340 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5340&view=rev Author: fabiomaulo Date: 2010-12-26 15:53:13 +0000 (Sun, 26 Dec 2010) Log Message: ----------- Fix NH-2470 Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Collection/PersistentIdentifierBag.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2470/Mappings.hbm.xml Modified: trunk/nhibernate/src/NHibernate/Collection/PersistentIdentifierBag.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Collection/PersistentIdentifierBag.cs 2010-12-25 20:55:56 UTC (rev 5339) +++ trunk/nhibernate/src/NHibernate/Collection/PersistentIdentifierBag.cs 2010-12-26 15:53:13 UTC (rev 5340) @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Data; using System.Diagnostics; +using System.Linq; +using Iesi.Collections.Generic; using NHibernate.DebugHelpers; using NHibernate.Engine; using NHibernate.Id; @@ -31,6 +33,48 @@ [DebuggerTypeProxy(typeof (CollectionProxy))] public class PersistentIdentifierBag : AbstractPersistentCollection, IList { + [Serializable] + private class SnapshotElement : IEquatable<SnapshotElement> + { + public object Id { get; set; } + public object Value { get; set; } + + public bool Equals(SnapshotElement other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return Equals(other.Id, Id); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != typeof (SnapshotElement)) + { + return false; + } + return Equals((SnapshotElement) obj); + } + + public override int GetHashCode() + { + return (Id != null ? Id.GetHashCode() : 0); + } + } + protected IList values; //element protected Dictionary<int, object> identifiers; //index -> id @@ -77,7 +121,7 @@ private object GetIdentifier(int index) { // NH specific : To emulate IDictionary behavior but using Dictionary<int, object> (without boxing/unboxing for index) - object result = null; + object result; identifiers.TryGetValue(index, out result); return result; } @@ -131,7 +175,7 @@ public override bool EqualsSnapshot(ICollectionPersister persister) { IType elementType = persister.ElementType; - IDictionary snap = (IDictionary) GetSnapshot(); + var snap = (ISet<SnapshotElement>) GetSnapshot(); if (snap.Count != values.Count) { return false; @@ -140,12 +184,7 @@ { object val = values[i]; object id = GetIdentifier(i); - if (id == null) - { - return false; - } - - object old = snap[id]; + object old = snap.Where(x=> Equals(x.Id, id)).Select(x=> x.Value).FirstOrDefault(); if (elementType.IsDirty(old, val, Session)) { return false; @@ -157,13 +196,13 @@ public override bool IsSnapshotEmpty(object snapshot) { - return ((IDictionary) snapshot).Count == 0; + return ((ICollection) snapshot).Count == 0; } public override IEnumerable GetDeletes(ICollectionPersister persister, bool indexIsFormula) { - IDictionary snap = (IDictionary) GetSnapshot(); - ArrayList deletes = new ArrayList(snap.Keys); + var snap = (ISet<SnapshotElement>)GetSnapshot(); + ArrayList deletes = new ArrayList(snap.Select(x=> x.Id).ToArray()); for (int i = 0; i < values.Count; i++) { if (values[i] != null) @@ -186,17 +225,18 @@ public override object GetSnapshotElement(object entry, int i) { - IDictionary snap = (IDictionary) GetSnapshot(); + var snap = (ISet<SnapshotElement>)GetSnapshot(); object id = GetIdentifier(i); - return snap[id]; + return snap.Where(x => Equals(x.Id, id)).Select(x => x.Value).FirstOrDefault(); } public override bool NeedsInserting(object entry, int i, IType elemType) { - IDictionary snap = (IDictionary) GetSnapshot(); + var snap = (ISet<SnapshotElement>)GetSnapshot(); object id = GetIdentifier(i); + object valueFound = snap.Where(x => Equals(x.Id, id)).Select(x => x.Value).FirstOrDefault(); - return entry != null && (id == null || snap[id] == null); + return entry != null && (id == null || valueFound == null); } public override bool NeedsUpdating(object entry, int i, IType elemType) @@ -205,7 +245,7 @@ { return false; } - IDictionary snap = (IDictionary) GetSnapshot(); + var snap = (ISet<SnapshotElement>)GetSnapshot(); object id = GetIdentifier(i); if (id == null) @@ -213,7 +253,7 @@ return false; } - object old = snap[id]; + object old = snap.Where(x => Equals(x.Id, id)).Select(x => x.Value).FirstOrDefault(); return old != null && elemType.IsDirty(old, entry, Session); } @@ -235,26 +275,22 @@ { EntityMode entityMode = Session.EntityMode; - Hashtable map = new Hashtable(values.Count); + var map = new HashedSet<SnapshotElement>(); int i = 0; foreach (object value in values) { - // NH Different behavior : in Hb they use directly identifiers[i++] - // probably we have some different behavior in some other place because a Snapshot before save the collection - // when the identifiers dictionary is empty (in this case the Snapshot is unneeded before save) object id; - if (identifiers.TryGetValue(i++, out id)) - { - map[id] = persister.ElementType.DeepCopy(value, entityMode, persister.Factory); - } + identifiers.TryGetValue(i++, out id); + var valueCopy = persister.ElementType.DeepCopy(value, entityMode, persister.Factory); + map.Add(new SnapshotElement { Id = id, Value = valueCopy }); } return map; } public override ICollection GetOrphans(object snapshot, string entityName) { - IDictionary sn = (IDictionary) snapshot; - return GetOrphans(sn.Values, values, entityName, Session); + var sn = (ISet<SnapshotElement>)GetSnapshot(); + return GetOrphans(sn.Select(x=> x.Value).ToArray(), values, entityName, Session); } public override void PreInsert(ICollectionPersister persister) Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2470/Mappings.hbm.xml =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2470/Mappings.hbm.xml 2010-12-25 20:55:56 UTC (rev 5339) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2470/Mappings.hbm.xml 2010-12-26 15:53:13 UTC (rev 5340) @@ -12,7 +12,7 @@ <version name="EntityVersion"/> <!-- NH2470 - I used to have inverse="true" here --> - <idbag name="Class2List" table="Class1_Class2" access="field.camelcase-underscore"> + <idbag name="Class2List" table="Class1_Class2" inverse="true" access="field.camelcase-underscore"> <collection-id column="ID" type="Guid"> <generator class="guid.comb" /> </collection-id> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |