示例#1
0
        /// <summary>
        /// Run-time implementation for copying the relationship data from object readers to corresponding entities.
        /// </summary>
        /// <param name="readerEntityPairs">The readers and their corresponding entities.</param>
        /// <param name="identityReader">Callback for reading the identities from the readers.</param>
        /// <param name="resourceResolver">Service for resolving identity values.</param>
        /// <param name="memberName">Name of the member.</param>
        /// <param name="relationshipId">ID of relationship being updated.</param>
        /// <param name="direction">Direction that the relationship is being updated.</param>
        /// <param name="mandatory">Indicates that the member is mandatory.</param>
        /// <param name="reporter">Target for any errors.</param>
        /// <param name="reportingName">Member name used for reporting.</param>
        /// <exception cref="ConnectorRequestException">
        /// </exception>
        private void RelationshipProcessorImpl(IEnumerable <ReaderEntityPair> readerEntityPairs, Func <IObjectReader, string, IReadOnlyCollection <object> > identityReader, IResourceResolver resourceResolver, string memberName, long relationshipId, Direction direction, bool mandatory, IImportReporter reporter, string reportingName)
        {
            if (reporter == null)
            {
                throw new ArgumentNullException(nameof(reporter));
            }

            // Get identifiers
            var identities           = new HashSet <object>( );
            var entitiesToIdentities = new Dictionary <IEntity, IReadOnlyCollection <object> >( );

            foreach (ReaderEntityPair pair in readerEntityPairs)
            {
                // Resolve targeted entity
                IReadOnlyCollection <object> targetResourceIdentities;
                IObjectReader reader = pair.ObjectReader;
                try
                {
                    targetResourceIdentities = identityReader(reader, memberName);

                    // Handle missing fields
                    if (mandatory && (!reader.HasKey(memberName) || targetResourceIdentities.Count == 0))
                    {
                        string message = string.Format(Messages.MandatoryPropertyMissing, reportingName);
                        reporter.ReportError(reader, message);
                        continue;
                    }
                }
                catch (FormatException)   // hmm .. this is a bit specific to the JSON reader
                {
                    reporter.ReportError(reader, Messages.IdentifierListContainedNulls);
                    continue;
                }

                if (targetResourceIdentities == null)
                {
                    continue;
                }

                foreach (object identity in targetResourceIdentities)
                {
                    if (identity == null || identity as string == string.Empty)
                    {
                        continue;
                    }
                    identities.Add(identity);
                }
                entitiesToIdentities.Add(pair.Entity, targetResourceIdentities);
            }

            // Resolve resources
            IDictionary <object, ResourceResolverEntry> resourceLookup = null;

            if (identities.Count > 0)
            {
                resourceLookup = resourceResolver.ResolveResources(identities.ToList());
            }

            // Update relationships
            foreach (ReaderEntityPair pair in readerEntityPairs)
            {
                IObjectReader reader       = pair.ObjectReader;
                IEntity       updateEntity = pair.Entity;
                IReadOnlyCollection <object> targetIdentities;
                if (!entitiesToIdentities.TryGetValue(updateEntity, out targetIdentities))
                {
                    continue;
                }

                // Update relationship
                var col = updateEntity.GetRelationships(relationshipId, direction);

                // Clearing is mandatory for lookups;
                // mandatory for relationships on new instances with default values;
                // and a good idea for other relationships.
                // Clearing will reset any default instances, but we've decided this is sensible, otherwise a subsequent update using the
                // same data would just clear them anyway. Default values do not get applied for mapped columns.
                col.Clear( );

                // Find each target identity in the lookup
                foreach (object targetIdentity in targetIdentities)
                {
                    if (targetIdentity == null)
                    {
                        continue;
                    }

                    ResourceResolverEntry entry;
                    if (resourceLookup == null || !resourceLookup.TryGetValue(targetIdentity, out entry))
                    {
                        reporter.ReportError(reader, Messages.ResourceNotFoundByField);
                        continue;
                    }
                    if (entry.Error != ResourceResolverError.None)
                    {
                        string message = ResourceResolver.FormatResolverError(entry.Error, targetIdentity.ToString( ));
                        reporter.ReportError(reader, message);
                        continue;
                    }

                    IEntity targetEntity = entry.Entity;

                    // And set into the relationship
                    if (targetEntity != null)
                    {
                        col.Add(targetEntity);
                    }
                }
            }
        }