Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 5 additions & 112 deletions src/NHibernate/Async/Collection/AbstractPersistentCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,8 +25,6 @@

namespace NHibernate.Collection
{
using System.Threading.Tasks;
using System.Threading;
public abstract partial class AbstractPersistentCollection : IPersistentCollection, ILazyInitializedCollection
{

Expand Down Expand Up @@ -91,42 +92,7 @@ public virtual Task ForceInitializationAsync(CancellationToken cancellationToken
}
return Task.CompletedTask;
}

public Task<ICollection> GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<ICollection>(cancellationToken);
}
try
{
if (HasQueuedOperations)
{
List<object> additions = new List<object>(operationQueue.Count);
List<object> removals = new List<object>(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<ICollection>(CollectionHelper.EmptyCollection);
}
catch (Exception ex)
{
return Task.FromException<ICollection>(ex);
}
}


/// <summary>
/// Called before inserting rows, to ensure that any surrogate keys are fully generated
/// </summary>
Expand All @@ -149,85 +115,12 @@ public virtual Task PreInsertAsync(ICollectionPersister persister, CancellationT
}
}

/// <summary>
/// Get all "orphaned" elements
/// </summary>
public abstract Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken);

/// <summary>
/// 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
/// </summary>
protected virtual async Task<ICollection> 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<object> res = new List<object>();

// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
var currentIds = new HashSet<TypedValue>();
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;
}

public async Task IdentityRemoveAsync(IList list, object obj, string entityName, ISessionImplementor session, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (obj != null && await (ForeignKeys.IsNotTransientSlowAsync(entityName, obj, session, cancellationToken)).ConfigureAwait(false))
{
IType idType = session.Factory.GetEntityPersister(entityName).IdentifierType;

object idOfCurrent = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, obj, session, cancellationToken)).ConfigureAwait(false);
List<object> toRemove = new List<object>(list.Count);
foreach (object current in list)
{
if (current == null)
{
continue;
}
object idOfOld = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, current, session, cancellationToken)).ConfigureAwait(false);
if (idType.IsEqual(idOfCurrent, idOfOld, session.Factory))
{
toRemove.Add(current);
}
}
foreach (object ro in toRemove)
{
list.Remove(ro);
}
IdentityRemove(list, obj, entityName, session.Factory);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ public override Task<IEnumerable> GetDeletesAsync(ICollectionPersister persister
return Task.FromException<IEnumerable>(ex);
}
}


// Since 5.3
[Obsolete("This method has no more usages and will be removed in a future version")]
public override Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
Expand All @@ -84,8 +86,7 @@ public override Task<ICollection> GetOrphansAsync(object snapshot, string entity
}
try
{
var sn = (ICollection) snapshot;
return GetOrphansAsync(sn, (ICollection) _gbag, entityName, Session, cancellationToken);
return Task.FromResult<ICollection>(GetOrphans(snapshot, entityName));
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ public override async Task<object> 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<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
Expand All @@ -164,8 +166,7 @@ public override Task<ICollection> GetOrphansAsync(object snapshot, string entity
}
try
{
var sn = (ISet<SnapshotElement>)GetSnapshot();
return GetOrphansAsync(sn.ToArray(x => x.Value), (ICollection) _values, entityName, Session, cancellationToken);
return Task.FromResult<ICollection>(GetOrphans(snapshot, entityName));
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ namespace NHibernate.Collection.Generic
using System.Threading;
public partial class PersistentGenericList<T> : AbstractPersistentCollection, IList<T>, IList, IQueryable<T>
{


// Since 5.3
[Obsolete("This method has no more usages and will be removed in a future version")]
public override Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
Expand All @@ -38,8 +40,7 @@ public override Task<ICollection> GetOrphansAsync(object snapshot, string entity
}
try
{
var sn = (IList<T>)snapshot;
return GetOrphansAsync((ICollection)sn, (ICollection) WrappedList, entityName, Session, cancellationToken);
return Task.FromResult<ICollection>(GetOrphans(snapshot, entityName));
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ namespace NHibernate.Collection.Generic
using System.Threading;
public partial class PersistentGenericMap<TKey, TValue> : AbstractPersistentCollection, IDictionary<TKey, TValue>, ICollection
{


// Since 5.3
[Obsolete("This method has no more usages and will be removed in a future version")]
public override Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
Expand All @@ -38,8 +40,7 @@ public override Task<ICollection> GetOrphansAsync(object snapshot, string entity
}
try
{
var sn = (IDictionary<TKey, TValue>) snapshot;
return GetOrphansAsync((ICollection)sn.Values, (ICollection)WrappedMap.Values, entityName, Session, cancellationToken);
return Task.FromResult<ICollection>(GetOrphans(snapshot, entityName));
}
catch (Exception ex)
{
Expand Down
11 changes: 4 additions & 7 deletions src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ namespace NHibernate.Collection.Generic
using System.Threading;
public partial class PersistentGenericSet<T> : AbstractPersistentCollection, ISet<T>, IQueryable<T>
{


// Since 5.3
[Obsolete("This method has no more usages and will be removed in a future version")]
public override Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
Expand All @@ -39,12 +41,7 @@ public override Task<ICollection> GetOrphansAsync(object snapshot, string entity
}
try
{
var sn = new SetSnapShot<T>((IEnumerable<T>)snapshot);

// TODO: Avoid duplicating shortcuts and array copy, by making base class GetOrphans() more flexible
if (WrappedSet.Count == 0) return Task.FromResult<ICollection>(sn);
if (((ICollection)sn).Count == 0) return Task.FromResult<ICollection>(sn);
return GetOrphansAsync(sn, WrappedSet.ToArray(), entityName, Session, cancellationToken);
return Task.FromResult<ICollection>(GetOrphans(snapshot, entityName));
}
catch (Exception ex)
{
Expand Down
20 changes: 2 additions & 18 deletions src/NHibernate/Async/Collection/IPersistentCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -19,8 +21,6 @@

namespace NHibernate.Collection
{
using System.Threading.Tasks;
using System.Threading;
public partial interface IPersistentCollection
{

Expand Down Expand Up @@ -92,27 +92,11 @@ public partial interface IPersistentCollection
/// </summary>
Task<IEnumerable> GetDeletesAsync(ICollectionPersister persister, bool indexIsFormula, CancellationToken cancellationToken);

/// <summary> Get the "queued" orphans</summary>
Task<ICollection> GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken);

/// <summary>
/// Called before inserting rows, to ensure that any surrogate keys are fully generated
/// </summary>
/// <param name="persister"></param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
Task PreInsertAsync(ICollectionPersister persister, CancellationToken cancellationToken);

/// <summary>
/// Get all "orphaned" elements
/// </summary>
/// <param name="snapshot">The snapshot of the collection.</param>
/// <param name="entityName">The persistent class whose objects
/// the collection is expected to contain.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
/// <returns>
/// An <see cref="ICollection"/> that contains all of the elements
/// that have been orphaned.
/// </returns>
Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken);
}
}
25 changes: 15 additions & 10 deletions src/NHibernate/Async/Collection/PersistentArrayHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,23 @@ namespace NHibernate.Collection
using System.Threading;
public partial class PersistentArrayHolder : AbstractPersistentCollection, ICollection
{

public override async Task<ICollection> 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<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
object[] sn = (object[]) snapshot;
object[] arr = (object[]) array;
List<object> result = new List<object>(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<ICollection>(cancellationToken);
}
try
{
return Task.FromResult<ICollection>(GetOrphans(snapshot, entityName));
}
catch (Exception ex)
{
return Task.FromException<ICollection>(ex);
}
return result;
}

public override async Task<bool> EqualsSnapshotAsync(ICollectionPersister persister, CancellationToken cancellationToken)
Expand Down Expand Up @@ -147,4 +152,4 @@ public override async Task<bool> NeedsUpdatingAsync(object entry, int i, IType e
&& await (elemType.IsDirtyAsync(array.GetValue(i), sn.GetValue(i), Session, cancellationToken)).ConfigureAwait(false);
}
}
}
}
4 changes: 2 additions & 2 deletions src/NHibernate/Async/Engine/Cascade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 0 additions & 13 deletions src/NHibernate/Async/Engine/CollectionEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,5 @@ public async Task PreFlushAsync(IPersistentCollection collection, CancellationTo
reached = false;
processed = false;
}

public Task<ICollection> 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<ICollection>(cancellationToken);
}
return collection.GetOrphansAsync(snapshot, entityName, cancellationToken);
}
}
}
Loading