public override async Task NullSafeSetAsync(DbCommand st, object value, int index, bool[] settable, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); object id; string entityName; if (value == null) { id = null; entityName = null; } else { entityName = session.BestGuessEntityName(value); id = await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, value, session, cancellationToken)).ConfigureAwait(false); } // metaType is assumed to be single-column type if (settable == null || settable[0]) { await(metaType.NullSafeSetAsync(st, entityName, index, session, cancellationToken)).ConfigureAwait(false); } if (settable == null) { await(identifierType.NullSafeSetAsync(st, id, index + 1, session, cancellationToken)).ConfigureAwait(false); } else { bool[] idsettable = new bool[settable.Length - 1]; Array.Copy(settable, 1, idsettable, 0, idsettable.Length); await(identifierType.NullSafeSetAsync(st, id, index + 1, idsettable, session, cancellationToken)).ConfigureAwait(false); } }
protected internal async Task <object> GetReferenceValueAsync(object value, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (value == null) { return(null); } else if (IsReferenceToPrimaryKey) { return(await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(GetAssociatedEntityName(), value, session, cancellationToken)).ConfigureAwait(false)); //tolerates nulls } else { IEntityPersister entityPersister = session.Factory.GetEntityPersister(GetAssociatedEntityName()); object propertyValue = entityPersister.GetPropertyValue(value, uniqueKeyPropertyName); // We now have the value of the property-ref we reference. However, // we need to dig a little deeper, as that property might also be // an entity type, in which case we need to resolve its identitifier IType type = entityPersister.GetPropertyType(uniqueKeyPropertyName); if (type.IsEntityType) { propertyValue = await(((EntityType)type).GetReferenceValueAsync(propertyValue, session, cancellationToken)).ConfigureAwait(false); } return(propertyValue); } }
public override async Task <object> DisassembleAsync(object value, ISessionImplementor session, object owner, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return(value == null ? null : new ObjectTypeCacheEntry(session.BestGuessEntityName(value), await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(session.BestGuessEntityName(value), value, session, cancellationToken)).ConfigureAwait(false))); }
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); } } }
private static async Task <object> IdAsync(object component, ISessionImplementor session, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); try { return(await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(session.BestGuessEntityName(component), component, session, cancellationToken)).ConfigureAwait(false)); } catch (TransientObjectException) { return(null); } }
public override async Task <object> ReplaceAsync(object original, object current, ISessionImplementor session, object owner, IDictionary copiedAlready, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (original == null) { return(null); } else { string entityName = session.BestGuessEntityName(original); object id = await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(entityName, original, session, cancellationToken)).ConfigureAwait(false); return(await(session.InternalLoadAsync(entityName, id, false, false, cancellationToken)).ConfigureAwait(false)); } }
protected internal Task <object> GetIdentifierAsync(object value, ISessionImplementor session, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <object>(cancellationToken)); } try { return(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(GetAssociatedEntityName(), value, session, cancellationToken)); //tolerates nulls } catch (Exception ex) { return(Task.FromException <object>(ex)); } }
/// <summary> /// Generates an identifier from the value of a Property. /// </summary> /// <param name="sessionImplementor">The <see cref="ISessionImplementor"/> this id is being generated in.</param> /// <param name="obj">The entity for which the id is being generated.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns> /// The identifier value from the associated object or /// <see cref="IdentifierGeneratorFactory.ShortCircuitIndicator"/> if the <c>session</c> /// already contains <c>obj</c>. /// </returns> public async Task <object> GenerateAsync(ISessionImplementor sessionImplementor, object obj, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); ISession session = (ISession)sessionImplementor; var persister = sessionImplementor.Factory.GetEntityPersister(entityName); object associatedObject = persister.GetPropertyValue(obj, propertyName); if (associatedObject == null) { throw new IdentifierGenerationException("attempted to assign id from null one-to-one property: " + propertyName); } EntityType foreignValueSourceType; IType propertyType = persister.GetPropertyType(propertyName); if (propertyType.IsEntityType) { foreignValueSourceType = (EntityType)propertyType; } else { // try identifier mapper foreignValueSourceType = (EntityType)persister.GetPropertyType("_identifierMapper." + propertyName); } object id; try { id = await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync( foreignValueSourceType.GetAssociatedEntityName(), associatedObject, sessionImplementor, cancellationToken)).ConfigureAwait(false); } catch (TransientObjectException) { id = await(session.SaveAsync(foreignValueSourceType.GetAssociatedEntityName(), associatedObject, cancellationToken)).ConfigureAwait(false); } if (session.Contains(obj)) { //abort the save (the object is already saved by a circular cascade) return(IdentifierGeneratorFactory.ShortCircuitIndicator); } return(id); }
public override async Task <object> DisassembleAsync(object value, ISessionImplementor session, object owner, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (value == null) { return(null); } object id = await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync(GetAssociatedEntityName(), value, session, cancellationToken)).ConfigureAwait(false); if (id == null) { throw new AssertionFailure("cannot cache a reference to an object with a null id: " + GetAssociatedEntityName()); } return(await(GetIdentifierType(session).DisassembleAsync(id, session, owner, cancellationToken)).ConfigureAwait(false)); }
/// <summary> /// Generates an identifier from the value of a Property. /// </summary> /// <param name="sessionImplementor">The <see cref="ISessionImplementor"/> this id is being generated in.</param> /// <param name="obj">The entity for which the id is being generated.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns> /// The identifier value from the associated object or /// <see cref="IdentifierGeneratorFactory.ShortCircuitIndicator"/> if the <c>session</c> /// already contains <c>obj</c>. /// </returns> public async Task <object> GenerateAsync(ISessionImplementor sessionImplementor, object obj, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var persister = sessionImplementor.Factory.GetEntityPersister(entityName); object associatedObject = persister.GetPropertyValue(obj, propertyName); if (associatedObject == null) { throw new IdentifierGenerationException("attempted to assign id from null one-to-one property: " + propertyName); } var foreignValueSourceType = GetForeignValueSourceType(persister); object id; try { id = await(ForeignKeys.GetEntityIdentifierIfNotUnsavedAsync( foreignValueSourceType.GetAssociatedEntityName(), associatedObject, sessionImplementor, cancellationToken)).ConfigureAwait(false); } catch (TransientObjectException) { if (sessionImplementor is ISession session) { id = await(session.SaveAsync(foreignValueSourceType.GetAssociatedEntityName(), associatedObject, cancellationToken)).ConfigureAwait(false); } else if (sessionImplementor is IStatelessSession statelessSession) { id = await(statelessSession.InsertAsync(foreignValueSourceType.GetAssociatedEntityName(), associatedObject, cancellationToken)).ConfigureAwait(false); } else { throw new IdentifierGenerationException("sessionImplementor is neither Session nor StatelessSession"); } } if (Contains(sessionImplementor, obj)) { //abort the save (the object is already saved by a circular cascade) return(IdentifierGeneratorFactory.ShortCircuitIndicator); } return(id); }
/// <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)); } } // 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))) { res.Add(old); } } return(res); }