diff --git a/src/NHibernate/Async/Collection/AbstractPersistentCollection.cs b/src/NHibernate/Async/Collection/AbstractPersistentCollection.cs index 00b1c3cccb3..ad7531bc12a 100644 --- a/src/NHibernate/Async/Collection/AbstractPersistentCollection.cs +++ b/src/NHibernate/Async/Collection/AbstractPersistentCollection.cs @@ -12,6 +12,9 @@ using System.Collections; using System.Collections.Generic; using System.Data.Common; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; using NHibernate.Collection.Generic; using NHibernate.Engine; using NHibernate.Impl; @@ -22,8 +25,6 @@ namespace NHibernate.Collection { - using System.Threading.Tasks; - using System.Threading; public abstract partial class AbstractPersistentCollection : IPersistentCollection, ILazyInitializedCollection { @@ -91,42 +92,7 @@ public virtual Task ForceInitializationAsync(CancellationToken cancellationToken } return Task.CompletedTask; } - - public Task GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - try - { - if (HasQueuedOperations) - { - List additions = new List(operationQueue.Count); - List removals = new List(operationQueue.Count); - for (int i = 0; i < operationQueue.Count; i++) - { - IDelayedOperation op = operationQueue[i]; - if (op.AddedInstance != null) - { - additions.Add(op.AddedInstance); - } - if (op.Orphan != null) - { - removals.Add(op.Orphan); - } - } - return GetOrphansAsync(removals, additions, entityName, session, cancellationToken); - } - - return Task.FromResult(CollectionHelper.EmptyCollection); - } - catch (Exception ex) - { - return Task.FromException(ex); - } - } - + /// /// Called before inserting rows, to ensure that any surrogate keys are fully generated /// @@ -149,60 +115,8 @@ public virtual Task PreInsertAsync(ICollectionPersister persister, CancellationT } } - /// - /// Get all "orphaned" elements - /// - public abstract Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken); - - /// - /// Given a collection of entity instances that used to - /// belong to the collection, and a collection of instances - /// that currently belong, return a collection of orphans - /// - protected virtual async Task GetOrphansAsync(ICollection oldElements, ICollection currentElements, string entityName, ISessionImplementor session, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - // short-circuit(s) - if (currentElements.Count == 0) - { - // no new elements, the old list contains only Orphans - return oldElements; - } - if (oldElements.Count == 0) - { - // no old elements, so no Orphans neither - return oldElements; - } - - IType idType = session.Factory.GetEntityPersister(entityName).IdentifierType; - - // create the collection holding the orphans - List res = new List(); - - // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access - var currentIds = new HashSet(); - foreach (object current in currentElements) - { - if (current != null && await (ForeignKeys.IsNotTransientSlowAsync(entityName, current, session, cancellationToken)).ConfigureAwait(false)) - { - object currentId = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, current, session, cancellationToken)).ConfigureAwait(false); - currentIds.Add(new TypedValue(idType, currentId, false)); - } - } - - // iterate over the *old* list - foreach (object old in oldElements) - { - object oldId = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, old, session, cancellationToken)).ConfigureAwait(false); - if (!currentIds.Contains(new TypedValue(idType, oldId, false))) - { - res.Add(old); - } - } - - return res; - } - + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public async Task IdentityRemoveAsync(IList list, object obj, string entityName, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs index 820d03c497d..1c24814eaf7 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs @@ -75,7 +75,9 @@ public override Task GetDeletesAsync(ICollectionPersister persister return Task.FromException(ex); } } - + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public override Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -85,7 +87,7 @@ public override Task GetOrphansAsync(object snapshot, string entity try { var sn = (ICollection) snapshot; - return GetOrphansAsync(sn, (ICollection) _gbag, entityName, Session, cancellationToken); + return Task.FromResult(GetOrphans(sn, (ICollection) _gbag, entityName, Session)); } catch (Exception ex) { diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs index 91dfc152861..1fa56e7a219 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs @@ -155,7 +155,9 @@ public override async Task ReadFromAsync(DbDataReader reader, ICollectio } return element; } - + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public override Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -165,7 +167,7 @@ public override Task GetOrphansAsync(object snapshot, string entity try { var sn = (ISet)GetSnapshot(); - return GetOrphansAsync(sn.ToArray(x => x.Value), (ICollection) _values, entityName, Session, cancellationToken); + return Task.FromResult(GetOrphans(sn.ToArray(x => x.Value), (ICollection) _values, entityName, Session)); } catch (Exception ex) { diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs index 260877f54b3..d1d936c75e6 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs @@ -29,7 +29,9 @@ namespace NHibernate.Collection.Generic using System.Threading; public partial class PersistentGenericList : AbstractPersistentCollection, IList, IList, IQueryable { - + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public override Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -39,7 +41,7 @@ public override Task GetOrphansAsync(object snapshot, string entity try { var sn = (IList)snapshot; - return GetOrphansAsync((ICollection)sn, (ICollection) WrappedList, entityName, Session, cancellationToken); + return Task.FromResult(GetOrphans((ICollection)sn, (ICollection) WrappedList, entityName, Session)); } catch (Exception ex) { diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs index 32819bb279b..2cc1e2208ae 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs @@ -29,7 +29,9 @@ namespace NHibernate.Collection.Generic using System.Threading; public partial class PersistentGenericMap : AbstractPersistentCollection, IDictionary, ICollection { - + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public override Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -39,7 +41,7 @@ public override Task GetOrphansAsync(object snapshot, string entity try { var sn = (IDictionary) snapshot; - return GetOrphansAsync((ICollection)sn.Values, (ICollection)WrappedMap.Values, entityName, Session, cancellationToken); + return Task.FromResult(GetOrphans((ICollection)sn.Values, (ICollection)WrappedMap.Values, entityName, Session)); } catch (Exception ex) { diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs index 693c8f0edbb..1de56b79889 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs @@ -30,7 +30,9 @@ namespace NHibernate.Collection.Generic using System.Threading; public partial class PersistentGenericSet : AbstractPersistentCollection, ISet, IQueryable { - + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public override Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -44,7 +46,7 @@ public override Task GetOrphansAsync(object snapshot, string entity // TODO: Avoid duplicating shortcuts and array copy, by making base class GetOrphans() more flexible if (WrappedSet.Count == 0) return Task.FromResult(sn); if (((ICollection)sn).Count == 0) return Task.FromResult(sn); - return GetOrphansAsync(sn, WrappedSet.ToArray(), entityName, Session, cancellationToken); + return Task.FromResult(GetOrphans(sn, WrappedSet.ToArray(), entityName, Session)); } catch (Exception ex) { diff --git a/src/NHibernate/Async/Collection/IPersistentCollection.cs b/src/NHibernate/Async/Collection/IPersistentCollection.cs index 14bdcec49fe..cd2bb132dcb 100644 --- a/src/NHibernate/Async/Collection/IPersistentCollection.cs +++ b/src/NHibernate/Async/Collection/IPersistentCollection.cs @@ -11,6 +11,8 @@ using System; using System.Collections; using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; using NHibernate.Collection.Generic; using NHibernate.Engine; using NHibernate.Loader; @@ -19,8 +21,6 @@ namespace NHibernate.Collection { - using System.Threading.Tasks; - using System.Threading; public partial interface IPersistentCollection { @@ -92,27 +92,11 @@ public partial interface IPersistentCollection /// Task GetDeletesAsync(ICollectionPersister persister, bool indexIsFormula, CancellationToken cancellationToken); - /// Get the "queued" orphans - Task GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken); - /// /// Called before inserting rows, to ensure that any surrogate keys are fully generated /// /// /// A cancellation token that can be used to cancel the work Task PreInsertAsync(ICollectionPersister persister, CancellationToken cancellationToken); - - /// - /// Get all "orphaned" elements - /// - /// The snapshot of the collection. - /// The persistent class whose objects - /// the collection is expected to contain. - /// A cancellation token that can be used to cancel the work - /// - /// An that contains all of the elements - /// that have been orphaned. - /// - Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken); } } diff --git a/src/NHibernate/Async/Collection/PersistentArrayHolder.cs b/src/NHibernate/Async/Collection/PersistentArrayHolder.cs index 4a8665de6f9..4ee04479a16 100644 --- a/src/NHibernate/Async/Collection/PersistentArrayHolder.cs +++ b/src/NHibernate/Async/Collection/PersistentArrayHolder.cs @@ -26,18 +26,23 @@ namespace NHibernate.Collection using System.Threading; public partial class PersistentArrayHolder : AbstractPersistentCollection, ICollection { - - public override async Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] + public override Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken) { - cancellationToken.ThrowIfCancellationRequested(); - object[] sn = (object[]) snapshot; - object[] arr = (object[]) array; - List result = new List(sn); - for (int i = 0; i < sn.Length; i++) + if (cancellationToken.IsCancellationRequested) { - await (IdentityRemoveAsync(result, arr[i], entityName, Session, cancellationToken)).ConfigureAwait(false); + return Task.FromCanceled(cancellationToken); + } + try + { + return Task.FromResult(GetOrphans((object[]) snapshot, (object[]) array, entityName, Session)); + } + catch (Exception ex) + { + return Task.FromException(ex); } - return result; } public override async Task EqualsSnapshotAsync(ICollectionPersister persister, CancellationToken cancellationToken) @@ -147,4 +152,4 @@ public override async Task NeedsUpdatingAsync(object entry, int i, IType e && await (elemType.IsDirtyAsync(array.GetValue(i), sn.GetValue(i), Session, cancellationToken)).ConfigureAwait(false); } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Async/Engine/Cascade.cs b/src/NHibernate/Async/Engine/Cascade.cs index f35b5686da1..e554de20988 100644 --- a/src/NHibernate/Async/Engine/Cascade.cs +++ b/src/NHibernate/Async/Engine/Cascade.cs @@ -285,11 +285,11 @@ private async Task DeleteOrphansAsync(string entityName, IPersistentCollection p if (pc.WasInitialized) { CollectionEntry ce = eventSource.PersistenceContext.GetCollectionEntry(pc); - orphans = ce == null ? CollectionHelper.EmptyCollection : await (ce.GetOrphansAsync(entityName, pc, cancellationToken)).ConfigureAwait(false); + orphans = ce == null ? CollectionHelper.EmptyCollection : ce.GetOrphans(entityName, pc); } else { - orphans = await (pc.GetQueuedOrphansAsync(entityName, cancellationToken)).ConfigureAwait(false); + orphans = pc.GetQueuedOrphans(entityName); } foreach (object orphan in orphans) diff --git a/src/NHibernate/Async/Engine/CollectionEntry.cs b/src/NHibernate/Async/Engine/CollectionEntry.cs index 97d590c3d37..ea5694df0fd 100644 --- a/src/NHibernate/Async/Engine/CollectionEntry.cs +++ b/src/NHibernate/Async/Engine/CollectionEntry.cs @@ -10,6 +10,8 @@ using System; using System.Collections; +using System.Threading; +using System.Threading.Tasks; using NHibernate.Action; using NHibernate.Collection; using NHibernate.Impl; @@ -17,8 +19,6 @@ namespace NHibernate.Engine { - using System.Threading.Tasks; - using System.Threading; public partial class CollectionEntry { @@ -70,18 +70,5 @@ public async Task PreFlushAsync(IPersistentCollection collection, CancellationTo reached = false; processed = false; } - - public Task GetOrphansAsync(string entityName, IPersistentCollection collection, CancellationToken cancellationToken) - { - if (snapshot == null) - { - throw new AssertionFailure("no collection snapshot for orphan delete"); - } - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - return collection.GetOrphansAsync(snapshot, entityName, cancellationToken); - } } } diff --git a/src/NHibernate/Async/Engine/ForeignKeys.cs b/src/NHibernate/Async/Engine/ForeignKeys.cs index 441dbcb87d4..df04ce9c177 100644 --- a/src/NHibernate/Async/Engine/ForeignKeys.cs +++ b/src/NHibernate/Async/Engine/ForeignKeys.cs @@ -157,10 +157,6 @@ private async Task IsNullifiableAsync(string entityName, object obj, Cance public static async Task IsNotTransientSlowAsync(string entityName, object entity, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - if (entity.IsProxy()) - return true; - if (session.PersistenceContext.IsEntryFor(entity)) - return true; return !await (IsTransientSlowAsync(entityName, entity, session, cancellationToken)).ConfigureAwait(false); } @@ -271,16 +267,6 @@ public static async Task GetEntityIdentifierIfNotUnsavedAsync(string ent if ((await (IsTransientFastAsync(entityName, entity, session, cancellationToken)).ConfigureAwait(false)).GetValueOrDefault()) { - /***********************************************/ - // TODO NH verify the behavior of NH607 test - // these lines are only to pass test NH607 during PersistenceContext porting - // i'm not secure that NH607 is a test for a right behavior - EntityEntry entry = session.PersistenceContext.GetEntry(entity); - if (entry != null) - return entry.Id; - // the check was put here to have les possible impact - /**********************************************/ - entityName = entityName ?? session.GuessEntityName(entity); string entityString = entity.ToString(); throw new TransientObjectException( diff --git a/src/NHibernate/Async/Type/IType.cs b/src/NHibernate/Async/Type/IType.cs index bbac991db9b..573628ccf5b 100644 --- a/src/NHibernate/Async/Type/IType.cs +++ b/src/NHibernate/Async/Type/IType.cs @@ -9,6 +9,7 @@ using System.Collections; +using System.Collections.Generic; using System.Data.Common; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -17,7 +18,7 @@ namespace NHibernate.Type { using System.Threading.Tasks; using System.Threading; - + public partial interface IType : ICacheAssembler { diff --git a/src/NHibernate/Collection/AbstractPersistentCollection.cs b/src/NHibernate/Collection/AbstractPersistentCollection.cs index 9387b9f8ff0..b63077e14d0 100644 --- a/src/NHibernate/Collection/AbstractPersistentCollection.cs +++ b/src/NHibernate/Collection/AbstractPersistentCollection.cs @@ -2,6 +2,9 @@ using System.Collections; using System.Collections.Generic; using System.Data.Common; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; using NHibernate.Collection.Generic; using NHibernate.Engine; using NHibernate.Impl; @@ -29,6 +32,28 @@ protected interface IDelayedOperation void Operate(); } + class TypeComparer : IEqualityComparer + { + private readonly IType _type; + private readonly ISessionFactoryImplementor _sessionFactory; + + public TypeComparer(IType type, ISessionFactoryImplementor sessionFactory) + { + _type = type; + _sessionFactory = sessionFactory; + } + + public new bool Equals(object x, object y) + { + return _type.IsEqual(x, y, _sessionFactory); + } + + public int GetHashCode(object obj) + { + return _type.GetHashCode(obj, _sessionFactory); + } + } + private class AdditionEnumerable : IEnumerable { private readonly AbstractPersistentCollection enclosingInstance; @@ -716,35 +741,62 @@ protected virtual ICollection GetOrphans(ICollection oldElements, ICollection cu return oldElements; } - IType idType = session.Factory.GetEntityPersister(entityName).IdentifierType; + if (currentElements.Count == oldElements.Count && currentElements.Cast().SequenceEqual(oldElements.Cast(), new IdentityEqualityComparer())) + return Array.Empty(); - // create the collection holding the orphans - List res = new List(); + var persister = session.Factory.GetEntityPersister(entityName); + IType idType = persister.IdentifierType; - // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access - var currentIds = new HashSet(); + var currentObjects = new HashSet(new TypeComparer(idType, session.Factory)); foreach (object current in currentElements) { - if (current != null && ForeignKeys.IsNotTransientSlow(entityName, current, session)) + if (current != null) { - object currentId = ForeignKeys.GetEntityIdentifierIfNotUnsaved(entityName, current, session); - currentIds.Add(new TypedValue(idType, currentId, false)); + var id = ForeignKeys.GetIdentifier(persister, current); + if (id != null) + currentObjects.Add(id); } } - // iterate over the *old* list + List res = new List(); + // oldElements may contain new elements (one case when session.Save is called on new object with collection filled with new objects) foreach (object old in oldElements) { - object oldId = ForeignKeys.GetEntityIdentifierIfNotUnsaved(entityName, old, session); - if (!currentIds.Contains(new TypedValue(idType, oldId, false))) + if (old != null) { - res.Add(old); + var id = ForeignKeys.GetIdentifier(persister, old); + if (id != null) + { + if (!currentObjects.Contains(id)) + { + res.Add(old); + } + } } } return res; } + // Since 5.3 + /// + /// Given a collection of entity instances that used to + /// belong to the collection, and a collection of instances + /// that currently belong, return a collection of orphans + /// + [Obsolete("This method has no more usages and will be removed in a future version")] + protected virtual Task GetOrphansAsync(ICollection oldElements, ICollection currentElements, string entityName, ISessionImplementor session, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + + return Task.FromResult(GetOrphans(oldElements, currentElements, entityName, session)); + } + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] public void IdentityRemove(IList list, object obj, string entityName, ISessionImplementor session) { if (obj != null && ForeignKeys.IsNotTransientSlow(entityName, obj, session)) @@ -866,6 +918,29 @@ public abstract object ReadFrom(DbDataReader reader, ICollectionPersister role, /// The anticipated size of the collection after initialization is complete. public abstract void BeforeInitialize(ICollectionPersister persister, int anticipatedSize); + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] + public Task GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + + try + { + return Task.FromResult(GetQueuedOrphans(entityName)); + } + catch (Exception ex) + { + return Task.FromException(ex); + } + } + + // Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] + public abstract Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken); + #region - Hibernate Collection Proxy Classes /* diff --git a/src/NHibernate/Collection/IPersistentCollection.cs b/src/NHibernate/Collection/IPersistentCollection.cs index 2021eceff12..cae02391957 100644 --- a/src/NHibernate/Collection/IPersistentCollection.cs +++ b/src/NHibernate/Collection/IPersistentCollection.cs @@ -1,6 +1,8 @@ using System; using System.Collections; using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; using NHibernate.Collection.Generic; using NHibernate.Engine; using NHibernate.Loader; @@ -304,6 +306,11 @@ public partial interface IPersistentCollection /// Get the "queued" orphans ICollection GetQueuedOrphans(string entityName); + // Since 5.3 + /// Get the "queued" orphans + [Obsolete("This method has no more usages and will be removed in a future version")] + Task GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken); + /// /// Clear the dirty flag, after flushing changes /// to the database. @@ -337,6 +344,21 @@ public partial interface IPersistentCollection /// that have been orphaned. /// ICollection GetOrphans(object snapshot, string entityName); + + //Since 5.3 + /// + /// Get all "orphaned" elements + /// + /// The snapshot of the collection. + /// The persistent class whose objects + /// the collection is expected to contain. + /// A cancellation token that can be used to cancel the work + /// + /// An that contains all of the elements + /// that have been orphaned. + /// + [Obsolete("This method has no more usages and will be removed in a future version")] + Task GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken); } // 6.0 TODO: merge into IPersistentCollection diff --git a/src/NHibernate/Collection/PersistentArrayHolder.cs b/src/NHibernate/Collection/PersistentArrayHolder.cs index 60739da6e96..242d7dac51a 100644 --- a/src/NHibernate/Collection/PersistentArrayHolder.cs +++ b/src/NHibernate/Collection/PersistentArrayHolder.cs @@ -94,14 +94,7 @@ public override bool IsSnapshotEmpty(object snapshot) public override ICollection GetOrphans(object snapshot, string entityName) { - object[] sn = (object[]) snapshot; - object[] arr = (object[]) array; - List result = new List(sn); - for (int i = 0; i < sn.Length; i++) - { - IdentityRemove(result, arr[i], entityName, Session); - } - return result; + return GetOrphans((object[]) snapshot, (object[]) array, entityName, Session); } public override bool IsWrapper(object collection) @@ -318,4 +311,4 @@ IEnumerator IEnumerable.GetEnumerator() #endregion } -} \ No newline at end of file +} diff --git a/src/NHibernate/Engine/CollectionEntry.cs b/src/NHibernate/Engine/CollectionEntry.cs index 038f07cbe76..a3c591bce32 100644 --- a/src/NHibernate/Engine/CollectionEntry.cs +++ b/src/NHibernate/Engine/CollectionEntry.cs @@ -1,5 +1,7 @@ using System; using System.Collections; +using System.Threading; +using System.Threading.Tasks; using NHibernate.Action; using NHibernate.Collection; using NHibernate.Impl; @@ -389,6 +391,23 @@ public ICollection GetOrphans(string entityName, IPersistentCollection collectio return collection.GetOrphans(snapshot, entityName); } + //Since 5.3 + [Obsolete("This method has no more usages and will be removed in a future version")] + public Task GetOrphansAsync(string entityName, IPersistentCollection collection, CancellationToken cancellationToken) + { + if (snapshot == null) + { + throw new AssertionFailure("no collection snapshot for orphan delete"); + } + + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + + return collection.GetOrphansAsync(snapshot, entityName, cancellationToken); + } + public bool IsSnapshotEmpty(IPersistentCollection collection) { return collection.WasInitialized && (LoadedPersister == null || LoadedPersister.IsMutable) && collection.IsSnapshotEmpty(Snapshot); diff --git a/src/NHibernate/Engine/ForeignKeys.cs b/src/NHibernate/Engine/ForeignKeys.cs index c48dbefaca9..91d3b0d0875 100644 --- a/src/NHibernate/Engine/ForeignKeys.cs +++ b/src/NHibernate/Engine/ForeignKeys.cs @@ -155,10 +155,6 @@ private bool IsNullifiable(string entityName, object obj) /// public static bool IsNotTransientSlow(string entityName, object entity, ISessionImplementor session) { - if (entity.IsProxy()) - return true; - if (session.PersistenceContext.IsEntryFor(entity)) - return true; return !IsTransientSlow(entityName, entity, session); } @@ -233,6 +229,11 @@ static bool HasDbSnapshot(string entityName, object entity, ISessionImplementor return snapshot == null; } + internal static object GetIdentifier(IEntityPersister persister, object entity) + { + return entity is INHibernateProxy proxy ? proxy.HibernateLazyInitializer.Identifier : persister.GetIdentifier(entity); + } + /// /// Return the identifier of the persistent or transient object, or throw /// an exception if the instance is "unsaved" @@ -265,16 +266,6 @@ public static object GetEntityIdentifierIfNotUnsaved(string entityName, object e if (IsTransientFast(entityName, entity, session).GetValueOrDefault()) { - /***********************************************/ - // TODO NH verify the behavior of NH607 test - // these lines are only to pass test NH607 during PersistenceContext porting - // i'm not secure that NH607 is a test for a right behavior - EntityEntry entry = session.PersistenceContext.GetEntry(entity); - if (entry != null) - return entry.Id; - // the check was put here to have les possible impact - /**********************************************/ - entityName = entityName ?? session.GuessEntityName(entity); string entityString = entity.ToString(); throw new TransientObjectException( diff --git a/src/NHibernate/IdentityEqualityComparer.cs b/src/NHibernate/IdentityEqualityComparer.cs index 26e52f6207d..9b4ac33ceca 100644 --- a/src/NHibernate/IdentityEqualityComparer.cs +++ b/src/NHibernate/IdentityEqualityComparer.cs @@ -1,14 +1,13 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Runtime.CompilerServices; namespace NHibernate { [Serializable] - public class IdentityEqualityComparer: IEqualityComparer + public class IdentityEqualityComparer : IEqualityComparer, IEqualityComparer { - #region IEqualityComparer Members - public int GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); @@ -32,8 +31,6 @@ public int GetHashCode(object obj) public new bool Equals(object x, object y) { return ReferenceEquals(x, y); - } - #endregion } } diff --git a/src/NHibernate/Type/IType.cs b/src/NHibernate/Type/IType.cs index 595084d9a67..675cab147d9 100644 --- a/src/NHibernate/Type/IType.cs +++ b/src/NHibernate/Type/IType.cs @@ -14,7 +14,7 @@ public static int GetOwnerColumnSpan(this IType type, IMapping sessionFactory) : type.GetColumnSpan(sessionFactory); } } - + /// /// Defines a mapping from a .NET to a SQL data-type. /// This interface is intended to be implemented by applications that need custom types.