示例#1
0
        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);
            }
        }
示例#2
0
        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);
            }
        }
示例#3
0
 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);
                }
            }
        }
示例#5
0
 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);
     }
 }
示例#6
0
 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));
     }
 }
示例#7
0
 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));
     }
 }
示例#8
0
        /// <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);
        }
示例#9
0
        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));
        }
示例#10
0
        /// <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);
        }