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); } }
protected internal object GetReferenceValue(object value, ISessionImplementor session) { if (value == null) { return(null); } else if (IsReferenceToPrimaryKey) { return(ForeignKeys.GetEntityIdentifierIfNotUnsaved(GetAssociatedEntityName(), value, session)); //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 = ((EntityType)type).GetReferenceValue(propertyValue, session); } return(propertyValue); } }
private async Task <object> MergeTransientEntityAsync(object entity, string entityName, object requestedId, IEventSource source, IDictionary copyCache, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); IEntityPersister persister = source.GetEntityPersister(entityName, entity); object id = persister.HasIdentifierProperty ? persister.GetIdentifier(entity) : null; object copy = null; if (copyCache.Contains(entity)) { copy = copyCache[entity]; persister.SetIdentifier(copy, id); } else { copy = source.Instantiate(persister, id); ((EventCache)copyCache).Add(entity, copy, true); // before cascade! } // cascade first, so that all unsaved objects get their // copy created before we actually copy //cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE); await(base.CascadeBeforeSaveAsync(source, persister, entity, copyCache, cancellationToken)).ConfigureAwait(false); await(CopyValuesAsync(persister, entity, copy, source, copyCache, ForeignKeyDirection.ForeignKeyFromParent, cancellationToken)).ConfigureAwait(false); try { // try saving; check for non-nullable properties that are null or transient entities before saving await(this.SaveTransientEntityAsync(copy, entityName, requestedId, source, copyCache, cancellationToken)).ConfigureAwait(false); } catch (PropertyValueException ex) { string propertyName = ex.PropertyName; object propertyFromCopy = persister.GetPropertyValue(copy, propertyName); object propertyFromEntity = persister.GetPropertyValue(entity, propertyName); IType propertyType = persister.GetPropertyType(propertyName); EntityEntry copyEntry = source.PersistenceContext.GetEntry(copy); if (propertyFromCopy == null || !propertyType.IsEntityType) { log.Info("property '{0}.{1}' is null or not an entity; {1} =[{2}]", copyEntry.EntityName, propertyName, propertyFromCopy); throw; } if (!copyCache.Contains(propertyFromEntity)) { log.Info("property '{0}.{1}' from original entity is not in copyCache; {1} =[{2}]", copyEntry.EntityName, propertyName, propertyFromEntity); throw; } if (((EventCache)copyCache).IsOperatedOn(propertyFromEntity)) { log.Info(ex, "property '{0}.{1}' from original entity is in copyCache and is in the process of being merged; {1} =[{2}]", copyEntry.EntityName, propertyName, propertyFromEntity); } else { log.Info(ex, "property '{0}.{1}' from original entity is in copyCache and is not in the process of being merged; {1} =[{2}]", copyEntry.EntityName, propertyName, propertyFromEntity); } // continue...; we'll find out if it ends up not getting saved later } // cascade first, so that all unsaved objects get their // copy created before we actually copy await(base.CascadeAfterSaveAsync(source, persister, entity, copyCache, cancellationToken)).ConfigureAwait(false); await(CopyValuesAsync(persister, entity, copy, source, copyCache, ForeignKeyDirection.ForeignKeyToParent, cancellationToken)).ConfigureAwait(false); return(copy); }