|
12 | 12 | using System.Collections;
|
13 | 13 | using System.Collections.Generic;
|
14 | 14 | using System.Data.Common;
|
| 15 | +using System.Linq; |
| 16 | +using System.Threading; |
| 17 | +using System.Threading.Tasks; |
15 | 18 | using NHibernate.Collection.Generic;
|
16 | 19 | using NHibernate.Engine;
|
17 | 20 | using NHibernate.Impl;
|
|
22 | 25 |
|
23 | 26 | namespace NHibernate.Collection
|
24 | 27 | {
|
25 |
| - using System.Threading.Tasks; |
26 |
| - using System.Threading; |
27 | 28 | public abstract partial class AbstractPersistentCollection : IPersistentCollection, ILazyInitializedCollection
|
28 | 29 | {
|
29 | 30 |
|
@@ -92,41 +93,6 @@ public virtual Task ForceInitializationAsync(CancellationToken cancellationToken
|
92 | 93 | return Task.CompletedTask;
|
93 | 94 | }
|
94 | 95 |
|
95 |
| - public Task<ICollection> GetQueuedOrphansAsync(string entityName, CancellationToken cancellationToken) |
96 |
| - { |
97 |
| - if (cancellationToken.IsCancellationRequested) |
98 |
| - { |
99 |
| - return Task.FromCanceled<ICollection>(cancellationToken); |
100 |
| - } |
101 |
| - try |
102 |
| - { |
103 |
| - if (HasQueuedOperations) |
104 |
| - { |
105 |
| - List<object> additions = new List<object>(operationQueue.Count); |
106 |
| - List<object> removals = new List<object>(operationQueue.Count); |
107 |
| - for (int i = 0; i < operationQueue.Count; i++) |
108 |
| - { |
109 |
| - IDelayedOperation op = operationQueue[i]; |
110 |
| - if (op.AddedInstance != null) |
111 |
| - { |
112 |
| - additions.Add(op.AddedInstance); |
113 |
| - } |
114 |
| - if (op.Orphan != null) |
115 |
| - { |
116 |
| - removals.Add(op.Orphan); |
117 |
| - } |
118 |
| - } |
119 |
| - return GetOrphansAsync(removals, additions, entityName, session, cancellationToken); |
120 |
| - } |
121 |
| - |
122 |
| - return Task.FromResult<ICollection>(CollectionHelper.EmptyCollection); |
123 |
| - } |
124 |
| - catch (Exception ex) |
125 |
| - { |
126 |
| - return Task.FromException<ICollection>(ex); |
127 |
| - } |
128 |
| - } |
129 |
| - |
130 | 96 | /// <summary>
|
131 | 97 | /// Called before inserting rows, to ensure that any surrogate keys are fully generated
|
132 | 98 | /// </summary>
|
@@ -154,79 +120,27 @@ public virtual Task PreInsertAsync(ICollectionPersister persister, CancellationT
|
154 | 120 | /// </summary>
|
155 | 121 | public abstract Task<ICollection> GetOrphansAsync(object snapshot, string entityName, CancellationToken cancellationToken);
|
156 | 122 |
|
157 |
| - /// <summary> |
158 |
| - /// Given a collection of entity instances that used to |
159 |
| - /// belong to the collection, and a collection of instances |
160 |
| - /// that currently belong, return a collection of orphans |
161 |
| - /// </summary> |
162 |
| - protected virtual async Task<ICollection> GetOrphansAsync(ICollection oldElements, ICollection currentElements, string entityName, ISessionImplementor session, CancellationToken cancellationToken) |
| 123 | + public async Task IdentityRemoveAsync(IList list, object obj, string entityName, ISessionImplementor session, CancellationToken cancellationToken) |
163 | 124 | {
|
164 | 125 | cancellationToken.ThrowIfCancellationRequested();
|
165 |
| - // short-circuit(s) |
166 |
| - if (currentElements.Count == 0) |
167 |
| - { |
168 |
| - // no new elements, the old list contains only Orphans |
169 |
| - return oldElements; |
170 |
| - } |
171 |
| - if (oldElements.Count == 0) |
172 |
| - { |
173 |
| - // no old elements, so no Orphans neither |
174 |
| - return oldElements; |
175 |
| - } |
176 |
| - |
177 |
| - IType idType = session.Factory.GetEntityPersister(entityName).IdentifierType; |
| 126 | + if (obj == null || await (ForeignKeys.IsTransientSlowAsync(entityName, obj, session, cancellationToken)).ConfigureAwait(false)) |
| 127 | + return; |
178 | 128 |
|
179 |
| - // create the collection holding the orphans |
180 |
| - List<object> res = new List<object>(); |
| 129 | + var persister = session.Factory.GetEntityPersister(entityName); |
| 130 | + IType idType = persister.IdentifierType; |
| 131 | + object idToRemove = ForeignKeys.GetIdentifier(persister, obj); |
181 | 132 |
|
182 |
| - // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access |
183 |
| - var currentIds = new HashSet<TypedValue>(); |
184 |
| - foreach (object current in currentElements) |
| 133 | + for (var index = list.Count - 1; index >= 0; index--) |
185 | 134 | {
|
186 |
| - if (current != null && await (ForeignKeys.IsNotTransientSlowAsync(entityName, current, session, cancellationToken)).ConfigureAwait(false)) |
| 135 | + object current = list[index]; |
| 136 | + if (current == null) |
187 | 137 | {
|
188 |
| - object currentId = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, current, session, cancellationToken)).ConfigureAwait(false); |
189 |
| - currentIds.Add(new TypedValue(idType, currentId, false)); |
| 138 | + continue; |
190 | 139 | }
|
191 |
| - } |
192 | 140 |
|
193 |
| - // iterate over the *old* list |
194 |
| - foreach (object old in oldElements) |
195 |
| - { |
196 |
| - object oldId = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, old, session, cancellationToken)).ConfigureAwait(false); |
197 |
| - if (!currentIds.Contains(new TypedValue(idType, oldId, false))) |
198 |
| - { |
199 |
| - res.Add(old); |
200 |
| - } |
201 |
| - } |
202 |
| - |
203 |
| - return res; |
204 |
| - } |
205 |
| - |
206 |
| - public async Task IdentityRemoveAsync(IList list, object obj, string entityName, ISessionImplementor session, CancellationToken cancellationToken) |
207 |
| - { |
208 |
| - cancellationToken.ThrowIfCancellationRequested(); |
209 |
| - if (obj != null && await (ForeignKeys.IsNotTransientSlowAsync(entityName, obj, session, cancellationToken)).ConfigureAwait(false)) |
210 |
| - { |
211 |
| - IType idType = session.Factory.GetEntityPersister(entityName).IdentifierType; |
212 |
| - |
213 |
| - object idOfCurrent = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, obj, session, cancellationToken)).ConfigureAwait(false); |
214 |
| - List<object> toRemove = new List<object>(list.Count); |
215 |
| - foreach (object current in list) |
216 |
| - { |
217 |
| - if (current == null) |
218 |
| - { |
219 |
| - continue; |
220 |
| - } |
221 |
| - object idOfOld = await (ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, current, session, cancellationToken)).ConfigureAwait(false); |
222 |
| - if (idType.IsEqual(idOfCurrent, idOfOld, session.Factory)) |
223 |
| - { |
224 |
| - toRemove.Add(current); |
225 |
| - } |
226 |
| - } |
227 |
| - foreach (object ro in toRemove) |
| 141 | + if (obj == current || idType.IsEqual(idToRemove, ForeignKeys.GetIdentifier(persister, current), session.Factory)) |
228 | 142 | {
|
229 |
| - list.Remove(ro); |
| 143 | + list.RemoveAt(index); |
230 | 144 | }
|
231 | 145 | }
|
232 | 146 | }
|
|
0 commit comments